Merge branch 'master' of github.com:flynx/object.js

This commit is contained in:
Alex A. Naanou 2020-04-30 17:13:51 +03:00
commit 888001b354
3 changed files with 89 additions and 43 deletions

View File

@ -201,23 +201,42 @@ sources(<object>, <name>, <callback>)
-> <list> -> <list>
``` ```
Get parent method
Get parent attribute value or method
``` ```
parent(<prototype>, <name>)
-> <parent-value>
-> undefined
parent(<method>, <this>) parent(<method>, <this>)
-> <parent-method> -> <parent-method>
-> undefined -> undefined
```
parent(<prototype>, <name>, <this>) _Edge case: The `parent(<method>, ..)` has one potential pitfall -- in
-> <parent-value> the rare case where a prototype chain contains two or more references
to the same method under the same name, `parent(..)` can't distinguish
between these references and will always return the second one._
Get parent property descriptor
```
parentProperty(<prototype>, <name>)
-> <prop-descriptor>
-> undefined -> undefined
``` ```
Get parent method and call it Get parent method and call it
``` ```
parentCall(<method>, <this>)
parentCall(<prototype>, <name>, <this>) parentCall(<prototype>, <name>, <this>)
-> <result> -> <result>
-> undefined -> undefined
parentCall(<method>, <this>)
-> <result>
-> undefined
``` ```
@ -227,6 +246,7 @@ mixin(<root>, <object>, ...)
-> <object> -> <object>
``` ```
Mixin contents of objects into one Mixin contents of objects into one
``` ```
mixinFlat(<root>, <object>, ...) mixinFlat(<root>, <object>, ...)
@ -235,6 +255,7 @@ mixinFlat(<root>, <object>, ...)
This is like `Object.assign(..)` but copies property objects rather than This is like `Object.assign(..)` but copies property objects rather than
property values. property values.
Make a raw (un-initialized) instance Make a raw (un-initialized) instance
``` ```
makeRawInstance(<context>, <constructor>, ...) makeRawInstance(<context>, <constructor>, ...)
@ -243,6 +264,7 @@ makeRawInstance(<context>, <constructor>, ...)
_EXPERIMENTAL: a shorthand to this is defined as `Constructor.__rawinstance__(context, ..)`_ _EXPERIMENTAL: a shorthand to this is defined as `Constructor.__rawinstance__(context, ..)`_
Define an object constructor Define an object constructor
``` ```
Constructor(<name>, <prototype>) Constructor(<name>, <prototype>)
@ -250,6 +272,7 @@ Constructor(<name>, <class-prototype>, <prototype>)
-> <constructor> -> <constructor>
``` ```
Shorthand to `Constructor(..)` Shorthand to `Constructor(..)`
``` ```
C(<name>, ..) C(<name>, ..)

View File

@ -6,8 +6,8 @@
* ...if yes then it would also be logical to move Object.run(..) here * ...if yes then it would also be logical to move Object.run(..) here
* *
**********************************************************************/ **********************************************************************/
((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define)( ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define)
function(require){ var module={} // makes module AMD/node compatible... (function(require){ var module={} // make module AMD/node compatible...
/*********************************************************************/ /*********************************************************************/
// Helpers... // Helpers...
@ -66,6 +66,8 @@ function(text, tab_size){
// -> list // -> list
// //
// //
// NOTE: this will not trigger any props...
//
// XXX should the callback(..) be used to break (current) or filter/map??? // XXX should the callback(..) be used to break (current) or filter/map???
// XXX revise name... // XXX revise name...
var sources = var sources =
@ -80,8 +82,9 @@ function(obj, name, callback){
stop = callback stop = callback
&& callback(obj) && callback(obj)
// stop requested by callback... // stop requested by callback...
if(stop === false || stop == 'stop'){ if(stop === true || stop == 'stop'){
return obj } } return res }
}
obj = obj.__proto__ obj = obj.__proto__
} while(obj !== null) } while(obj !== null)
return res } return res }
@ -90,7 +93,7 @@ function(obj, name, callback){
// Find the next parent attribute in the prototype chain. // Find the next parent attribute in the prototype chain.
// //
// Get parent attribute value... // Get parent attribute value...
// parent(value, name, this) // parent(proto, name)
// -> value> // -> value>
// -> undefined // -> undefined
// //
@ -108,7 +111,7 @@ function(obj, name, callback){
// //
// method: function(){ // method: function(){
// // get attribute... // // get attribute...
// var a = object.parent(X.prototype.attr, 'attr', this) // var a = object.parent(X.prototype, 'attr')
// //
// // get method... // // get method...
// var ret = object.parent(X.prototype.method, this).call(this, ...arguments) // var ret = object.parent(X.prototype.method, this).call(this, ...arguments)
@ -130,37 +133,64 @@ function(obj, name, callback){
// loops, for example, this.method deep in a chain will resolve to // loops, for example, this.method deep in a chain will resolve to
// the first .method value visible from 'this', i.e. the top most // the first .method value visible from 'this', i.e. the top most
// value and not the value visible from that particular level... // value and not the value visible from that particular level...
// NOTE: in the general case this will get the value of the returned
// property/attribute, the rest of the way passive to props.
// The method case will get the value of every method from 'this'
// and to the method after the match.
var parent = var parent =
module.parent = module.parent =
function(proto, name, that){ function(proto, name){
// special case: method... // special case: method...
if(arguments.length == 2){ if(typeof(name) != typeof('str')){
var method = proto that = name
proto = that = name name = proto.name
name = method.name // get first matching source...
// skip until we get to the current method... proto = sources(that, name,
while(proto.__proto__ && proto[name] !== method){ function(obj){ return obj[name] === proto })
proto = proto.__proto__ .pop() }
} // get first source...
} var res = sources(proto, name,
// skip till next name occurrence... function(obj){ return 'stop' })
while(proto.__proto__ && !proto.hasOwnProperty(name)){ .pop()
proto = proto.__proto__ return res ?
} // get next value...
// get next value... res.__proto__[name]
return proto.__proto__[name] } : undefined }
// Find the next parent property descriptor in the prototype chain...
//
// parentProperty(proto, name)
// -> prop-descriptor
//
//
// This is like parent(..) but will get a property descriptor...
//
var parentProperty =
module.parentProperty =
function(proto, name){
// get second source...
var c = 0
var res = sources(proto, name,
function(obj){ return c++ == 1 })
.pop()
return res ?
// get next value...
Object.getOwnPropertyDescriptor(res, name)
: undefined }
// Find the next parent method and call it... // Find the next parent method and call it...
// //
// parentCall(meth, this, ...)
// parentCall(proto, name, this, ...) // parentCall(proto, name, this, ...)
// parentCall(meth, this, ...)
// -> res // -> res
// -> undefined // -> undefined
// //
// //
// This also gracefully handles the case when no higher level definition // This also gracefully handles the case when no higher level definition
// is found, i.e. the corresponding parent(..) call will return undefined. // is found, i.e. the corresponding parent(..) call will return undefined
// or a non-callable.
// //
// NOTE: this is just like parent(..) but will call the retrieved method, // NOTE: this is just like parent(..) but will call the retrieved method,
// essentially this is a shorthand to: // essentially this is a shorthand to:
@ -168,20 +198,14 @@ function(proto, name, that){
// or: // or:
// parent(method, this).call(this, ...) // parent(method, this).call(this, ...)
// NOTE: for more docs see parent(..) // NOTE: for more docs see parent(..)
//
// XXX should we rename this to parent.call(..) ???
// ...this does not care about context so there is no reason to keep
// the default call, but this lowers discoverability and might be
// confusing...
var parentCall = var parentCall =
module.parentCall = module.parentCall =
function(proto, name, that, ...args){ function(proto, name, that, ...args){
var [p, c] = typeof(name) == typeof('str') ? var meth = parent(proto, name)
[ [proto, name, that], [...arguments].slice(2)]
: [ [proto, name], [...arguments].slice(1)]
var meth = parent(...p)
return meth instanceof Function ? return meth instanceof Function ?
meth.call(...c) meth.call(...( typeof(name) == typeof('str') ?
[...arguments].slice(2)
: [...arguments].slice(1) ))
: undefined } : undefined }
@ -498,8 +522,7 @@ function Constructor(name, a, b){
enumerable: false, enumerable: false,
}) })
return _constructor return _constructor }
}

View File

@ -1,6 +1,6 @@
{ {
"name": "ig-object", "name": "ig-object",
"version": "2.4.6", "version": "2.6.0",
"description": "", "description": "",
"main": "object.js", "main": "object.js",
"scripts": { "scripts": {