mirror of
				https://github.com/flynx/pWiki.git
				synced 2025-10-31 11:00:08 +00:00 
			
		
		
		
	updated local deps...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									6655d985ec
								
							
						
					
					
						commit
						113084652f
					
				
							
								
								
									
										1870
									
								
								lib/actions.js
									
									
									
									
									
								
							
							
						
						
									
										1870
									
								
								lib/actions.js
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1370
									
								
								lib/features.js
									
									
									
									
									
								
							
							
						
						
									
										1370
									
								
								lib/features.js
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										625
									
								
								lib/object.js
									
									
									
									
									
								
							
							
						
						
									
										625
									
								
								lib/object.js
									
									
									
									
									
								
							| @ -1,50 +1,403 @@ | |||||||
| /********************************************************************** | /********************************************************************** | ||||||
| *  | *  | ||||||
|  | * object.js | ||||||
| * | * | ||||||
|  | * Repo and docs: | ||||||
|  | * 	https://github.com/flynx/object.js
 | ||||||
|  | * | ||||||
|  | * | ||||||
|  | * XXX should this extend Object??? | ||||||
|  | * 		...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...
 | ||||||
|  | 
 | ||||||
|  | var TAB_SIZE = | ||||||
|  | module.TAB_SIZE = 4 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | // Normalize indent...
 | ||||||
| /*********************************************************************/ |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| // Make a JavaScrip object constructor...	
 |  | ||||||
| //
 | //
 | ||||||
|  | // 	normalizeIndent(text)
 | ||||||
|  | // 		-> text
 | ||||||
|  | //
 | ||||||
|  | //
 | ||||||
|  | // This will remove common indent from each like of text, this is useful 
 | ||||||
|  | // for printing function code of functions that were defined at deep 
 | ||||||
|  | // levels of indent.
 | ||||||
|  | //
 | ||||||
|  | // NOTE: this will trim out both leading and trailing white-space.
 | ||||||
|  | //
 | ||||||
|  | // XXX is this the right place for this???
 | ||||||
|  | // 		...when moving take care that ImageGrid's core.doc uses this...
 | ||||||
|  | var normalizeIndent = | ||||||
|  | module.normalizeIndent = | ||||||
|  | function(text, tab_size){ | ||||||
|  | 	tab_size = tab_size || TAB_SIZE | ||||||
|  | 	text = tab_size > 0 ? | ||||||
|  | 		text.replace(/\t/g, ' '.repeat(tab_size)) | ||||||
|  | 		: text | ||||||
|  | 	var lines = text.split(/\n/) | ||||||
|  | 	var l = lines  | ||||||
|  | 		.reduce(function(l, e, i){ | ||||||
|  | 			var indent = e.length - e.trimLeft().length | ||||||
|  | 			return e.trim().length == 0  | ||||||
|  | 					// ignore 0 indent of first line...
 | ||||||
|  | 					|| (i == 0 && indent == 0) ? l  | ||||||
|  | 				: l < 0 ?  | ||||||
|  | 					indent  | ||||||
|  | 				: Math.min(l, indent) | ||||||
|  | 		}, -1) | ||||||
|  | 	return lines | ||||||
|  | 		.map(function(line, i){  | ||||||
|  | 			return i == 0 ?  | ||||||
|  | 				line  | ||||||
|  | 				: line.slice(l) }) | ||||||
|  | 		.join('\n') | ||||||
|  | 		.trim() } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | // Prototype chain content access...
 | ||||||
|  | 
 | ||||||
|  | // Get a list of source objects for a prop/attr name...
 | ||||||
|  | //
 | ||||||
|  | // 	sources(obj, name)
 | ||||||
|  | // 	sources(obj, name, callback)
 | ||||||
|  | // 		-> list
 | ||||||
|  | // 		-> []
 | ||||||
|  | // 		
 | ||||||
|  | // 	callback(obj)
 | ||||||
|  | // 		-> true | 'stop'
 | ||||||
|  | // 		-> ..
 | ||||||
|  | // 		
 | ||||||
|  | // 		
 | ||||||
|  | // The callback(..) is called with each matching object.
 | ||||||
|  | // 
 | ||||||
|  | // The callback(..) can be used to break/stop the search, returning 
 | ||||||
|  | // a partial list og matcges up untill and including the object 
 | ||||||
|  | // triggering the stop.
 | ||||||
|  | //
 | ||||||
|  | //
 | ||||||
|  | // NOTE: this go up the prototype chain, not caring about any role (
 | ||||||
|  | // 		instance/class or instance/prototype) bounderies and depends 
 | ||||||
|  | // 		only on the object given as the starting point.
 | ||||||
|  | // 		It is possible to start the search from this, thus checking
 | ||||||
|  | // 		for any overloading in the instance, though this approach is 
 | ||||||
|  | // 		not very reusable....
 | ||||||
|  | // NOTE: this will not trigger any props...
 | ||||||
|  | var sources = | ||||||
|  | module.sources = | ||||||
|  | function(obj, name, callback){ | ||||||
|  | 	var stop | ||||||
|  | 	var res = [] | ||||||
|  | 	do { | ||||||
|  | 		if(obj.hasOwnProperty(name)){ | ||||||
|  | 			res.push(obj)  | ||||||
|  | 			// handle callback...
 | ||||||
|  | 			stop = callback | ||||||
|  | 				&& callback(obj) | ||||||
|  | 			// stop requested by callback...
 | ||||||
|  | 			if(stop === true || stop == 'stop'){ | ||||||
|  | 				return res }  | ||||||
|  | 		} | ||||||
|  | 		obj = obj.__proto__ | ||||||
|  | 	} while(obj !== null) | ||||||
|  | 	return res } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // Find the next parent attribute in the prototype chain.
 | ||||||
|  | //
 | ||||||
|  | // 	Get parent attribute value...
 | ||||||
|  | // 	parent(proto, name)
 | ||||||
|  | // 		-> value
 | ||||||
|  | // 		-> undefined
 | ||||||
|  | //
 | ||||||
|  | // 	Get parent method...
 | ||||||
|  | // 	parent(method, this)
 | ||||||
|  | // 		-> meth
 | ||||||
|  | // 		-> undefined
 | ||||||
|  | //
 | ||||||
|  | // 
 | ||||||
|  | // The two forms differ in:
 | ||||||
|  | // 	- in parent(method, ..) a method's .name attr is used for name.
 | ||||||
|  | // 	- in parent(method, ..) the containing prototype is inferred.
 | ||||||
|  | //
 | ||||||
|  | // NOTE: there are cases where method.name is not set (e.g. anonymous 
 | ||||||
|  | // 		function), so there a name should be passed explicitly...
 | ||||||
|  | // NOTE: when passing a method it is recommended to pass an explicit 
 | ||||||
|  | // 		reference to it relative to the constructor, i.e.:
 | ||||||
|  | // 			Constructor.prototype.method
 | ||||||
|  | // 		this will avoid relative resolution loops, for example: 
 | ||||||
|  | // 			this.method 
 | ||||||
|  | // 		deep in a chain will resolve to the first .method value visible 
 | ||||||
|  | // 		from 'this', i.e. the top most value and not the value visible
 | ||||||
|  | // 		from that particular level...
 | ||||||
|  | //
 | ||||||
|  | //
 | ||||||
|  | // Example:
 | ||||||
|  | // 		var X = object.Constructor('X', {
 | ||||||
|  | //			__proto__: Y.prototype,
 | ||||||
|  | //
 | ||||||
|  | //			attr: 123,
 | ||||||
|  | //
 | ||||||
|  | // 			method: function(){
 | ||||||
|  | // 				// get attribute...
 | ||||||
|  | // 				var a = object.parent(X.prototype, 'attr')
 | ||||||
|  | //
 | ||||||
|  | // 				// get method...
 | ||||||
|  | // 				var ret = object.parent(X.prototype.method, this)
 | ||||||
|  | // 					.call(this, ...arguments)
 | ||||||
|  | //
 | ||||||
|  | // 				// ...
 | ||||||
|  | // 			}
 | ||||||
|  | // 		})
 | ||||||
|  | //
 | ||||||
|  | //
 | ||||||
|  | // 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.
 | ||||||
|  | // NOTE: this is super(..) replacement, usable in any context without 
 | ||||||
|  | // 		restriction -- super(..) is restricted to class methods only...
 | ||||||
|  | var parent = | ||||||
|  | module.parent = | ||||||
|  | function(proto, name){ | ||||||
|  | 	// special case: method...
 | ||||||
|  | 	if(typeof(name) != typeof('str')){ | ||||||
|  | 		that = name | ||||||
|  | 		name = proto.name | ||||||
|  | 		// get first matching source...
 | ||||||
|  | 		proto = sources(that, name,  | ||||||
|  | 				function(obj){ return obj[name] === proto }) | ||||||
|  | 			.pop() } | ||||||
|  | 	// get first source...
 | ||||||
|  | 	var res = sources(proto, name,  | ||||||
|  | 			function(obj){ return 'stop' }) | ||||||
|  | 		.pop()  | ||||||
|  | 	return res ? | ||||||
|  | 		// get next value...
 | ||||||
|  | 		res.__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...
 | ||||||
|  | //
 | ||||||
|  | // 	parentCall(proto, name, this, ...)
 | ||||||
|  | // 	parentCall(meth, this, ...)
 | ||||||
|  | // 		-> res
 | ||||||
|  | // 		-> undefined
 | ||||||
|  | //
 | ||||||
|  | //
 | ||||||
|  | // This also gracefully handles the case when no higher level definition 
 | ||||||
|  | // 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,
 | ||||||
|  | // 		essentially this is a shorthand to:
 | ||||||
|  | // 			parent(proto, name).call(this, ...)
 | ||||||
|  | // 		or:
 | ||||||
|  | // 			parent(method, this).call(this, ...)
 | ||||||
|  | // NOTE: for more docs see parent(..)
 | ||||||
|  | var parentCall = | ||||||
|  | module.parentCall = | ||||||
|  | function(proto, name, that, ...args){ | ||||||
|  | 	var meth = parent(proto, name) | ||||||
|  | 	return meth instanceof Function ? | ||||||
|  | 		meth.call(...( typeof(name) == typeof('str') ? | ||||||
|  | 			[...arguments].slice(2) | ||||||
|  | 			: [...arguments].slice(1) )) | ||||||
|  | 		: undefined } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | // Mixin utils...
 | ||||||
|  | // XXX should we add mixout(..) and friends ???
 | ||||||
|  | 
 | ||||||
|  | // Mix a set of methods/props/attrs into an object...
 | ||||||
|  | // 
 | ||||||
|  | //	mixinFlat(root, object, ...)
 | ||||||
|  | //		-> root
 | ||||||
|  | //
 | ||||||
|  | //
 | ||||||
|  | // NOTE: essentially this is just like Object.assign(..) but copies 
 | ||||||
|  | // 		properties directly rather than copying property values...
 | ||||||
|  | var mixinFlat =  | ||||||
|  | module.mixinFlat =  | ||||||
|  | function(root, ...objects){ | ||||||
|  | 	return objects | ||||||
|  | 		.reduce(function(root, cur){ | ||||||
|  | 			Object.keys(cur) | ||||||
|  | 				.map(function(k){ | ||||||
|  | 					Object.defineProperty(root, k, | ||||||
|  | 						Object.getOwnPropertyDescriptor(cur, k)) }) | ||||||
|  | 			return root }, root) } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // Mix sets of methods/props/attrs into an object as prototypes...
 | ||||||
|  | //
 | ||||||
|  | // 	mixin(root, object, ...)
 | ||||||
|  | // 		-> root
 | ||||||
|  | //
 | ||||||
|  | //
 | ||||||
|  | // This will create a new object per set of methods given and 
 | ||||||
|  | // mixinFlat(..) the method set into this object leaving the 
 | ||||||
|  | // original objects intact.
 | ||||||
|  | // 
 | ||||||
|  | // 		root <-- object1_copy <-- .. <-- objectN_copy
 | ||||||
|  | // 				
 | ||||||
|  | var mixin =  | ||||||
|  | module.mixin =  | ||||||
|  | function(root, ...objects){ | ||||||
|  | 	return objects | ||||||
|  | 		.reduce(function(res, cur){ | ||||||
|  | 			return module.mixinFlat(Object.create(res), cur) }, root) } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //---------------------------------------------------------------------
 | ||||||
|  | // Constructor...
 | ||||||
|  | 
 | ||||||
|  | // Make an uninitialized instance object...
 | ||||||
|  | //
 | ||||||
|  | // 	makeRawInstance(context, constructor, ...)
 | ||||||
|  | // 		-> 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__(..)
 | ||||||
|  | //
 | ||||||
|  | //
 | ||||||
|  | // NOTE: context is only used when passeding to .__new__(..) if defined, 
 | ||||||
|  | // 		and is ignored otherwise...
 | ||||||
|  | // NOTE: as this is simply an extension to the base JavaScript protocol this
 | ||||||
|  | // 		can be used to construct any object...
 | ||||||
|  | // 		Example:
 | ||||||
|  | // 			var O = function(){}
 | ||||||
|  | // 			// new is optional...
 | ||||||
|  | // 			var o = new makeRawInstance(null, O)
 | ||||||
|  | // NOTE: .__new__(..) is intentionaly an instance method (contary to 
 | ||||||
|  | // 		Python) this is done because there are no classes in JS and 
 | ||||||
|  | // 		adding and instance constructor as a class method would create 
 | ||||||
|  | // 		unneccessary restrictions both on the "class" object and on the 
 | ||||||
|  | // 		instance...
 | ||||||
|  | // 
 | ||||||
|  | // XXX Q: should the context (this) in .__new__(..) be _constructor or 
 | ||||||
|  | // 		.prototype???
 | ||||||
|  | // 		... .prototype seems to be needed more often but through it we 
 | ||||||
|  | // 		can't reach the actual constructor... but on the other hand we 
 | ||||||
|  | // 		can (should?) always explicitly use it -- .__new__(..) is usually 
 | ||||||
|  | // 		in the same scope + this makes it more reusable for chaining
 | ||||||
|  | // 		.__new__(..) calls...
 | ||||||
|  | // 		...currently it's .prototype...
 | ||||||
|  | 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 an object constructor function...
 | ||||||
| //
 | //
 | ||||||
| // 	Make a constructor with an object prototype...
 | // 	Make a constructor with an object prototype...
 | ||||||
| // 		makeConstructor(<name>, <proto>)
 | // 		Constructor(name, proto)
 | ||||||
| // 			-> constructor
 |  | ||||||
| //
 |  | ||||||
| // 	Make a constructor with an init function prototype...
 |  | ||||||
| // 		makeConstructor(<name>, <init-func>)
 |  | ||||||
| // 			-> constructor
 | // 			-> constructor
 | ||||||
| //
 | //
 | ||||||
| // 	Make a constructor with a prototype (object/function) and a class
 | // 	Make a constructor with a prototype (object/function) and a class
 | ||||||
| // 	prototype...
 | // 	prototype...
 | ||||||
| // 		makeConstructor(<name>, <proto>, <class-proto>)
 | // 		Constructor(name, class-proto, proto)
 | ||||||
| // 		makeConstructor(<name>, <init-func>, <class-proto>)
 |  | ||||||
| // 			-> constructor
 | // 			-> constructor
 | ||||||
| // 			NOTE: the <class-proto> defines a set of class methods and 
 | // 			NOTE: the <class-proto> defines a set of class methods and 
 | ||||||
| // 					attributes.
 | // 					attributes.
 | ||||||
| //
 | //
 | ||||||
| //
 | //
 | ||||||
| //
 |  | ||||||
| // The resulting constructor can produce objects in one of these ways:
 | // The resulting constructor can produce objects in one of these ways:
 | ||||||
| //
 | //
 | ||||||
| // 	Basic constructor use...
 | // 	Create instance...
 | ||||||
| // 		constructor()
 | // 		constructor(..)
 | ||||||
| // 		new constructor
 | // 		new constructor
 | ||||||
| // 		new constructor()
 | // 		new constructor(..)
 | ||||||
| // 			-> instance
 | // 			-> instance
 | ||||||
| //
 | //
 | ||||||
| // 	Pass arguments to the constructor...
 | //	Create raw/uninitialized instance...
 | ||||||
| // 		constructor(<arg>[, ...])
 | //		constructor.__rawinstance__(..)
 | ||||||
| // 		new constructor(<arg>[, ...])
 | //		makeRawInstance(null, constructor, ..)
 | ||||||
| // 			-> instance
 | //			-> raw-instance
 | ||||||
| //
 | //
 | ||||||
| //
 | //
 | ||||||
| // All produced objects are instances of the constructor
 | // All produced objects are instances of the constructor
 | ||||||
| @ -53,28 +406,65 @@ function(require){ var module={} // makes module AMD/node compatible... | |||||||
| //
 | //
 | ||||||
| //
 | //
 | ||||||
| //
 | //
 | ||||||
| // Init protocol:
 | // Create and initialization protocol:
 | ||||||
| // 	1) the base instance object is prepared (.__proto__ is set)
 | // 	1) raw instance is created:
 | ||||||
| // 	2) if <init-func> is present, then it is called with instance as 
 | // 		a) constructor.__rawinstance__(..) / makeRawInstance(..) called:
 | ||||||
| // 		context and passed the constructor arguments
 | // 			- call .__new__(..) if defined and get return value as 
 | ||||||
| // 	3) if <proto>.__init__(..) is present, it is called with the instance
 | // 				instance, or
 | ||||||
| // 		as context and passed the constructor arguments.
 | // 			- if .__call__(..) defined or prototype is a function, wrap 
 | ||||||
|  | // 				it and use the wrapper function as instance, or
 | ||||||
|  | // 			- create an empty object
 | ||||||
|  | // 		b) instance linked to prototype chain
 | ||||||
|  | // 			set .__proto__ to constructor.prototype
 | ||||||
|  | // 	2) instance is initialized: 
 | ||||||
|  | // 		call .__init__(..) if defined
 | ||||||
|  | // 
 | ||||||
|  | //
 | ||||||
|  | // 
 | ||||||
|  | // Special methods (constructor):
 | ||||||
|  | //
 | ||||||
|  | //  Handle uninitialized instance construction
 | ||||||
|  | // 	.__rawinstance__(context, ...)
 | ||||||
|  | // 		-> instance
 | ||||||
|  | // 		NOTE: This is a shorthand to makeRawInstance(..) see it for 
 | ||||||
|  | // 			details.
 | ||||||
|  | // 
 | ||||||
|  | // 
 | ||||||
|  | // Special methods (.prototype):
 | ||||||
|  | //
 | ||||||
|  | // 	Create new instance object...
 | ||||||
|  | // 	.__new__(context, ..)
 | ||||||
|  | // 		-> object
 | ||||||
|  | //
 | ||||||
|  | // 	Handle instance call...
 | ||||||
|  | // 	.__call__(context, ..)
 | ||||||
|  | // 		-> ..
 | ||||||
|  | //
 | ||||||
|  | // 	Initialize instance object...
 | ||||||
|  | // 	.__init__(..)
 | ||||||
|  | // 		-> ..
 | ||||||
|  | //
 | ||||||
|  | //
 | ||||||
|  | // NOTE: raw instance creation is defined by makeRawInstance(..) so see 
 | ||||||
|  | // 		it for more info.
 | ||||||
|  | // NOTE: raw instance creation can be completely overloaded by defining
 | ||||||
|  | // 		.__rawinstance__(..) on the constructor.
 | ||||||
| //
 | //
 | ||||||
| //
 | //
 | ||||||
| //
 | //
 | ||||||
| // Inheritance:
 | // Inheritance:
 | ||||||
| // 	A simple way to build C -> B -> A chain would be:
 | // 	A simple way to build C -> B -> A chain would be:
 | ||||||
| //
 | //
 | ||||||
| // 		var A = makeConstructor('A', {})
 | // 		// NOTE: new is optional...
 | ||||||
|  | // 		var A = new Constructor('A')
 | ||||||
| //
 | //
 | ||||||
| // 		// NOTE: the prototype is an instance and not a constructor,
 | // 		// NOTE: in a prototype chain the prototypes are "inherited"
 | ||||||
| // 		//		this is obvious if one considers that in JS there are
 | // 		// NOTE: JS has no classes and the prototype is just another 
 | ||||||
| // 		//		no classes and inheritance is done via object prototypes
 | // 		//		object, the only difference is that it's used by the 
 | ||||||
| // 		//		but this might be a gotcha to people coming from the 
 | // 		//		constructor to link other objects i.e. "instances" to...
 | ||||||
| // 		//		class-object world.
 | // 		var B = Constructor('B', {__proto__: A.prototype})
 | ||||||
| // 		var B = makeConstructor('B', A())
 |  | ||||||
| //
 | //
 | ||||||
| // 		var C = makeConstructor('C', B())
 | // 		var C = Constructor('C', Objec.create(B.prototype))
 | ||||||
| //
 | //
 | ||||||
| // 		var c = C()
 | // 		var c = C()
 | ||||||
| //
 | //
 | ||||||
| @ -89,12 +479,12 @@ function(require){ var module={} // makes module AMD/node compatible... | |||||||
| //
 | //
 | ||||||
| //
 | //
 | ||||||
| // Motivation:
 | // Motivation:
 | ||||||
| // 	The general motivation here is to standardise the constructor protocol
 | // 	The general motivation here is to standardise the constructor 
 | ||||||
| // 	and make a single simple way to go with minimal variation. This is due
 | // 	protocol and make a single simple way to go with minimal variation. 
 | ||||||
| // 	to the JavaScript base protocol though quite simple, being too flexible
 | // 	This is due to the JavaScript base protocol though quite simple, 
 | ||||||
| // 	making it very involved to produce objects in a consistent manner by 
 | // 	being too flexible making it very involved to produce objects in a 
 | ||||||
| // 	hand, especially in long running projects, in turn spreading all the 
 | // 	consistent manner by hand, especially in long running projects, 
 | ||||||
| // 	refactoring over multiple sites and styles.
 | // 	in turn spreading all the refactoring over multiple sites and styles.
 | ||||||
| //
 | //
 | ||||||
| // 	This removes part of the flexibility and in return gives us:
 | // 	This removes part of the flexibility and in return gives us:
 | ||||||
| // 		- single, well defined protocol
 | // 		- single, well defined protocol
 | ||||||
| @ -103,111 +493,74 @@ function(require){ var module={} // makes module AMD/node compatible... | |||||||
| // 		- easy refactoring without touching the client code
 | // 		- easy refactoring without touching the client code
 | ||||||
| //
 | //
 | ||||||
| //
 | //
 | ||||||
| // NOTE: this sets the proto's .constructor attribute, this rendering it
 | // NOTE: this sets the proto's .constructor attribute, thus rendering it
 | ||||||
| // 		not reusable, to use the same prototype for multiple objects clone
 | // 		not reusable, to use the same prototype for multiple objects 
 | ||||||
| // 		it via. Object.create(..) or copy it...
 | // 		clone it via. Object.create(..) or copy it...
 | ||||||
| //
 | // NOTE: to disable .__rawinstance__(..) handling set it to false in the 
 | ||||||
| // XXX might be a good idea to be able to make an instance without 
 | // 		class prototype...
 | ||||||
| // 		initializing it...
 | var Constructor =  | ||||||
| // 		...mainly for inheritance.
 | module.Constructor = | ||||||
| // 		...would also be helpful in this case to call all the 
 | // shorthand...
 | ||||||
| // 		constructors in the chain
 | module.C = | ||||||
| var makeConstructor = | function Constructor(name, a, b){ | ||||||
| module.makeConstructor = |  | ||||||
| function makeConstructor(name, a, b){ |  | ||||||
| 	var proto = b == null ? a : b | 	var proto = b == null ? a : b | ||||||
| 	var cls_proto = b == null ? b : a | 	var cls_proto = b == null ? b : a | ||||||
|  | 	proto = proto || {} | ||||||
| 
 | 
 | ||||||
|  | 	// the actual constructor...
 | ||||||
| 	var _constructor = function Constructor(){ | 	var _constructor = function Constructor(){ | ||||||
| 		/* | 		// create raw instance...
 | ||||||
| 		// XXX BUG: if the constructor is called from it's instance this will 
 | 		var obj = _constructor.__rawinstance__ ?  | ||||||
| 		// 		return the instance and not a new object...
 | 				_constructor.__rawinstance__(this, ...arguments) | ||||||
| 		// in case this is called as a function (without new)...
 | 			: makeRawInstance(this, _constructor, ...arguments) | ||||||
| 		if(this.constructor !== _constructor){ | 		// initialize...
 | ||||||
| 			// NOTE: the following does the job of the 'new' operator but
 | 		obj.__init__ instanceof Function | ||||||
| 			// 		with one advantage, we can now pass arbitrary args 
 | 			&& obj.__init__(...arguments) | ||||||
| 			// 		in...
 | 		return obj } | ||||||
| 			// 		This is equivalent to:
 |  | ||||||
| 			//			return new _constructor(json)
 |  | ||||||
| 			var obj = {} |  | ||||||
| 			obj.__proto__ = _constructor.prototype |  | ||||||
| 			// XXX for some reason this does not resolve from .__proto__
 |  | ||||||
| 			obj.constructor = _constructor |  | ||||||
| 			//obj.__proto__.constructor = _constructor
 |  | ||||||
| 
 | 
 | ||||||
| 		} else { | 	_constructor.name = name | ||||||
| 			var obj = this | 	// 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
 | ||||||
| 		// NOTE: the following does the job of the 'new' operator but
 | 		// 		static and never infuenced by external inputs...
 | ||||||
| 		// 		with one advantage, we can now pass arbitrary args 
 | 		&& eval('_constructor = '+ _constructor | ||||||
| 		// 		in...
 |  | ||||||
| 		// 		This is equivalent to:
 |  | ||||||
| 		//			return new _constructor(json)
 |  | ||||||
| 		var obj = {} |  | ||||||
| 		obj.__proto__ = _constructor.prototype |  | ||||||
| 		// XXX for some reason this does not resolve from .__proto__
 |  | ||||||
| 		// XXX this also is a regular attr and not a prop...
 |  | ||||||
| 		//obj.constructor = _constructor
 |  | ||||||
| 		Object.defineProperty(obj, 'constructor', { |  | ||||||
| 			value: _constructor, |  | ||||||
| 			enumerable: false, |  | ||||||
| 		}) |  | ||||||
| 		//obj.__proto__.constructor = _constructor
 |  | ||||||
| 
 |  | ||||||
| 		// explicit init...
 |  | ||||||
| 		if(proto instanceof Function){ |  | ||||||
| 			proto.apply(obj, arguments) |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		// load initial state...
 |  | ||||||
| 		if(obj.__init__ != null){ |  | ||||||
| 			obj.__init__.apply(obj, arguments) |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		return obj |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/* XXX for some reason this works for the _constructor but all  |  | ||||||
| 	 * 		instances get the wrong name resolved... |  | ||||||
| 	Object.defineProperty(_constructor, 'name', { |  | ||||||
| 		value: name, |  | ||||||
| 	}) |  | ||||||
| 	*/ |  | ||||||
| 
 |  | ||||||
| 	// just in case the browser refuses to change the name, we'll make it
 |  | ||||||
| 	// a different offer ;)
 |  | ||||||
| 	if(_constructor.name == 'Constructor'){ |  | ||||||
| 			// skip for chrome app...
 |  | ||||||
| 			//&& !(window.chrome && chrome.runtime && chrome.runtime.id)){
 |  | ||||||
| 		eval('_constructor = '+ _constructor |  | ||||||
| 				.toString() | 				.toString() | ||||||
| 				.replace(/Constructor/g, name)) | 				.replace(/Constructor/g, name)) | ||||||
| 	} | 	// set .toString(..)...
 | ||||||
| 
 | 	// NOTE: do this only if .toString(..) is not defined by user...
 | ||||||
|  | 	;((cls_proto || {}).toString() == ({}).toString()) | ||||||
|  | 		&& Object.defineProperty(_constructor, 'toString', { | ||||||
|  | 			value: function(){  | ||||||
|  | 				var args = proto.__init__ ? | ||||||
|  | 					proto.__init__ | ||||||
|  | 						.toString() | ||||||
|  | 						.split(/\n/)[0] | ||||||
|  | 							.replace(/function\(([^)]*)\){.*/, '$1') | ||||||
|  | 					: '' | ||||||
|  | 				var code = proto.__init__ ? | ||||||
|  | 					proto.__init__ | ||||||
|  | 						.toString() | ||||||
|  | 						.replace(/[^{]*{/, '{') | ||||||
|  | 					: '{ .. }' | ||||||
|  | 				return `${this.name}(${args})${normalizeIndent(code)}` }, | ||||||
|  | 			enumerable: false, | ||||||
|  | 		}) | ||||||
| 	_constructor.__proto__ = cls_proto | 	_constructor.__proto__ = cls_proto | ||||||
| 	_constructor.prototype = proto | 	_constructor.prototype = proto | ||||||
| 	_constructor.prototype.constructor = _constructor | 	// generic raw instance constructor...
 | ||||||
|  | 	_constructor.__rawinstance__ instanceof Function | ||||||
|  | 		|| (_constructor.__rawinstance__ =  | ||||||
|  | 			function(context, ...args){ | ||||||
|  | 				return makeRawInstance(context, this, ...args) }) | ||||||
| 
 | 
 | ||||||
| 	return _constructor | 	// set .prototype.constructor
 | ||||||
| } | 	Object.defineProperty(_constructor.prototype, 'constructor', { | ||||||
|  | 		value: _constructor, | ||||||
|  | 		enumerable: false, | ||||||
|  | 	}) | ||||||
| 
 | 
 | ||||||
| 
 | 	return _constructor } | ||||||
| // super equivalent...
 |  | ||||||
| //
 |  | ||||||
| // 	superMethod(<class>, <method-name>).call(this, ...)
 |  | ||||||
| // 		-> <result>
 |  | ||||||
| //
 |  | ||||||
| // This will return a next method in inheritance chain after <class> by
 |  | ||||||
| // its name (<method-name>).
 |  | ||||||
| // In the normal use-case <class> is the current class and <method-name>
 |  | ||||||
| // is the name of the current method.
 |  | ||||||
| var superMethod = |  | ||||||
| module.superMethod = |  | ||||||
| function superMethod(cls, meth){ |  | ||||||
| 	return cls.prototype.__proto__[meth] |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user