From 535aeab9b02ace1fa640dd27214a3a00d4812029 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Sun, 26 Apr 2020 19:30:49 +0300 Subject: [PATCH] more refactoring and experimenting... Signed-off-by: Alex A. Naanou --- README.md | 5 ++ object.js | 145 ++++++++++++++++++++++++++++++--------------------- package.json | 2 +- 3 files changed, 91 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index a2282dc..17cdc04 100755 --- a/README.md +++ b/README.md @@ -198,6 +198,11 @@ mixinFlat(, , ...) This is like `Object.assign(..)` but copies property objects rather than property values. +Make a raw instance +``` +makeRawInstance(, , ...) + -> +``` Define an object constructor ``` diff --git a/object.js b/object.js index 94ad4c3..77e945b 100755 --- a/object.js +++ b/object.js @@ -156,8 +156,72 @@ function(root, ...objects){ //--------------------------------------------------------------------- -// Make a JavaScrip object constructor... +// Make/get the base instance object... // +// makeRawInstance(context, constructor, ...args) +// -> instance +// +// +// This will: +// - construct an object +// - if .__new__(..) is defined +// -> call and use its return value +// - if prototype is a function or if .__call__(..) is defined +// -> use a wrapper function +// - else +// -> use {} +// - link the object into the prototype chain +// +// +// This will not call .__init__(..) +// +// XXX Q: should this be a class method or a utility??? +// XXX Q: should .__new__(..) be a class method??? +var makeRawInstance = +module.makeRawInstance = +function(context, constructor, ...args){ + var _mirror_doc = + function(func, target){ + Object.defineProperty(func, 'toString', { + value: function(...args){ + return target.toString(...args) }, + enumerable: false, + }) + return func } + + var obj = + // prototype defines .__new__(..)... + constructor.prototype.__new__ instanceof Function ? + constructor.prototype.__new__(context, ...args) + // callable instance -- prototype is a function... + // NOTE: we need to isolate the .prototype from instances... + : constructor.prototype instanceof Function ? + _mirror_doc( + function(){ + return constructor.prototype.call(obj, this, ...arguments) }, + constructor.prototype) + // callable instance -- prototype defines .__call__(..)... + // NOTE: we need to isolate the .__call__ from instances... + : constructor.prototype.__call__ instanceof Function ? + _mirror_doc( + function(){ + return constructor.prototype.__call__.call(obj, this, ...arguments) }, + constructor.prototype.__call__) + // default object base... + : {} + + // link to prototype chain... + obj.__proto__ = constructor.prototype + Object.defineProperty(obj, 'constructor', { + value: constructor, + enumerable: false, + }) + + return obj } + + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Make a JavaScrip object constructor... // // Make a constructor with an object prototype... // Constructor(, ) @@ -258,11 +322,9 @@ function(root, ...objects){ // not reusable, to use the same prototype for multiple objects clone // it via. Object.create(..) or copy it... // -// XXX might be a good idea to be able to make an instance without -// initializing it... -// ...mainly for inheritance. -// ...would also be helpful in this case to call all the -// constructors in the chain +// XXX Q: should the context in .__new__(..) be _constructor or .prototype??? +// ...currently it's .prototype... +// XXX Q: should we add a wrapper to .makeRawInstance(..) as a class method here??? var Constructor = module.Constructor = // shorthand... @@ -272,61 +334,19 @@ function Constructor(name, a, b){ var cls_proto = b == null ? b : a proto = proto || {} - // mirror doc from target to func... - var _mirror = function(func, target){ - Object.defineProperty(func, 'toString', { - value: function(...args){ - return target.toString(...args) }, - enumerable: false, - }) - return func } - + // the actual constructor... var _constructor = function Constructor(){ - // NOTE: the following does the job of the 'new' operator but - // with one advantage, we can now pass arbitrary args - // in... - // This is equivalent to: - // return new _constructor(json) - var obj = - // prototype defines .__new__(..)... - // XXX should the context here he _constructor or .prototype (now)??? - _constructor.prototype.__new__ instanceof Function ? - _constructor.prototype.__new__(this, ...arguments) - // prototype is a function... - // NOTE: we need to isolate the .prototype from instances... - : _constructor.prototype instanceof Function ? - _mirror( - function(){ - return _constructor.prototype.call(obj, this, ...arguments) }, - _constructor.prototype) - // prototype defines .__call__(..)... - // NOTE: we need to isolate the .__call__ from instances... - // XXX should this be instanceof Function??? - : _constructor.prototype.__call__ instanceof Function ? - _mirror( - function(){ - return _constructor.prototype.__call__.call(obj, this, ...arguments) }, - _constructor.prototype.__call__) - // default object base... - : {} - - // XXX should this be done when .__new__(..) is called??? - obj.__proto__ = _constructor.prototype - Object.defineProperty(obj, 'constructor', { - value: _constructor, - enumerable: false, - }) - - // load initial state... + var obj = makeRawInstance(this, _constructor, ...arguments) obj.__init__ instanceof Function && obj.__init__(...arguments) + return obj } - return obj - } - - // just in case the browser refuses to change the name, we'll make it - // a different offer ;) + _constructor.name = name + // just in case the browser refuses to change the name, we'll make + // it a different offer ;) _constructor.name == 'Constructor' + // NOTE: this eval(..) should not be a risk as its inputs are + // static and never infuenced by external inputs... && eval('_constructor = '+ _constructor .toString() .replace(/Constructor/g, name)) @@ -347,14 +367,20 @@ function Constructor(name, a, b){ .toString() .replace(/[^{]*{/, '{') : '{ .. }' - - return `${this.name}(${args})${normalizeIndent(code)}` - }, + return `${this.name}(${args})${normalizeIndent(code)}` }, enumerable: false, }) _constructor.__proto__ = cls_proto _constructor.prototype = proto + // XXX EXPERIMENTAL... + // wrapper to makeRawInstance(..)... + _constructor.__rawinstance__ = function(...args){ + return (_constructor.__proto__ || {}).__rawinstance__ ? + // XXX revise / test... + // XXX should we hardcode cls_proto here??? + _constructor.__proto__.__rawinstance__.call(this, ...args) + : makeRawInstance(this, _constructor, ...args) } Object.defineProperty(_constructor.prototype, 'constructor', { value: _constructor, enumerable: false, @@ -365,6 +391,5 @@ function Constructor(name, a, b){ - /********************************************************************** * vim:set ts=4 sw=4 : */ return module }) diff --git a/package.json b/package.json index 5019c37..42aad0f 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ig-object", - "version": "2.2.2", + "version": "2.3.0", "description": "", "main": "object.js", "scripts": {