diff --git a/README.md b/README.md index 8eccb19f..84889a52 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Statements coverage|99.76%||90%|*9.08% ignored* Branches coverage|99.26%||90%|*16.17% ignored* Functions coverage|100%||90%|*9% ignored* Maintainability|82.25||70| -Number of tests||364||*pending: 0, duration: 615ms* +Number of tests||364||*pending: 0, duration: 912ms* Number of sources||41|| Lines of code|92|3782|| @@ -60,6 +60,7 @@ Version | Label | Release | Debug | Plato ------ | ----- | ----- | ----- | ----- [0.1.5](https://github.com/ArnaudBuchholz/gpf-js/tree/v0.1.5) / [doc](https://arnaudbuchholz.github.io/gpf/0.1.5/doc/index.html) | The new core | [lib](https://arnaudbuchholz.github.io/gpf/0.1.5/gpf.js) / [test](https://arnaudbuchholz.github.io/gpf/test.html?release=0.1.5) | [lib](https://arnaudbuchholz.github.io/gpf/0.1.5/gpf-debug.js) / [test](https://arnaudbuchholz.github.io/gpf/test.html?debug=0.1.5) | [plato](https://arnaudbuchholz.github.io/gpf/0.1.5/plato/index.html) [0.1.6](https://github.com/ArnaudBuchholz/gpf-js/tree/v0.1.6) / [doc](https://arnaudbuchholz.github.io/gpf/0.1.6/doc/index.html) | gpf.define | [lib](https://arnaudbuchholz.github.io/gpf/0.1.6/gpf.js) / [test](https://arnaudbuchholz.github.io/gpf/test.html?release=0.1.6) | [lib](https://arnaudbuchholz.github.io/gpf/0.1.6/gpf-debug.js) / [test](https://arnaudbuchholz.github.io/gpf/test.html?debug=0.1.6) | [plato](https://arnaudbuchholz.github.io/gpf/0.1.6/plato/index.html) +[0.1.7](https://github.com/ArnaudBuchholz/gpf-js/tree/v0.1.7) / [doc](https://arnaudbuchholz.github.io/gpf/0.1.7/doc/index.html) | Securing gpf.define | [lib](https://arnaudbuchholz.github.io/gpf/0.1.7/gpf.js) / [test](https://arnaudbuchholz.github.io/gpf/test.html?release=0.1.7) | [lib](https://arnaudbuchholz.github.io/gpf/0.1.7/gpf-debug.js) / [test](https://arnaudbuchholz.github.io/gpf/test.html?debug=0.1.7) | [plato](https://arnaudbuchholz.github.io/gpf/0.1.7/plato/index.html) ## Credits diff --git a/build/gpf-debug.js b/build/gpf-debug.js index 2e15e5ad..7d420239 100644 --- a/build/gpf-debug.js +++ b/build/gpf-debug.js @@ -35,7 +35,7 @@ * GPF Version * @since 0.1.5 */ - _gpfVersion = "0.1.6", + _gpfVersion = "0.1.7", /** * Host constants * @since 0.1.5 @@ -293,6 +293,22 @@ callback.call(thisArg, array[index], index, array); } } + function _gpfObjectForEachOwnProperty(object, callback, thisArg) { + for (var property in object) { + /* istanbul ignore else */ + if (object.hasOwnProperty(property)) { + callback.call(thisArg, object[property], property, object); + } + } + } + /* istanbul ignore next */ + // Microsoft cscript / wscript specific version + function _gpfObjectForEachOwnPropertyWScript(object, callback, thisArg) { + _gpfObjectForEachOwnProperty(object, callback, thisArg); + if (object.hasOwnProperty("constructor")) { + callback.call(thisArg, object.constructor, "constructor", object); + } + } /** * Similar to [].forEach but for objects * @@ -301,13 +317,13 @@ * @param {*} [thisArg] thisArg Value to use as this when executing callback * @since 0.1.5 */ - function _gpfObjectForEach(object, callback, thisArg) { - for (var property in object) { - /* istanbul ignore else */ - if (object.hasOwnProperty(property)) { - callback.call(thisArg, object[property], property, object); - } - } + var _gpfObjectForEach; + /* istanbul ignore if */ + // Microsoft cscript / wscript specific version + if (_GPF_HOST.WSCRIPT === _gpfHost) { + _gpfObjectForEach = _gpfObjectForEachOwnPropertyWScript; + } else { + _gpfObjectForEach = _gpfObjectForEachOwnProperty; } /** * Executes a provided function once per structure element. @@ -885,9 +901,21 @@ return this.name; }; } //endregion + function _gpfObjectAssign(value, memberName) { + /*jshint validthis:true*/ + this[memberName] = value; //eslint-disable-line no-invalid-this + } _gpfInstallCompatibility("Object", { on: Object, statics: { + // Introduced with ECMAScript 2015 + assign: function (destination, source) { + _gpfIgnore(source); + [].slice.call(arguments, 1).forEach(function (nthSource) { + _gpfObjectForEach(nthSource, _gpfObjectAssign, destination); + }); + return destination; + }, // Introduced with JavaScript 1.8.5 create: function () { function Temp() { @@ -1352,32 +1380,8 @@ } return _gpfContext(path.split(".")); }; - function _gpfAssign(value, memberName) { - /*jshint validthis:true*/ - this[memberName] = value; - } - /** - * Extends the destination object by copying own enumerable properties from the source object. - * If the member already exists, it is overwritten. - * - * @param {Object} destination Destination object - * @param {...Object} source Source objects - * @return {Object} Destination object - * @since 0.1.5 - */ - function _gpfExtend(destination, source) { - _gpfIgnore(source); - [].slice.call(arguments, 1).forEach(function (nthSource) { - _gpfObjectForEach(nthSource, _gpfAssign, destination); - }); - return destination; - } - /** - * @gpf:sameas _gpfExtend - * @since 0.1.5 - */ - gpf.extend = _gpfExtend; - _gpfStringEscapes.html = _gpfExtend(_gpfStringEscapes.xml, { + gpf.extend = Object.assign; + _gpfStringEscapes.html = Object.assign({}, _gpfStringEscapes.xml, { "à": "à", "á": "á", "è": "è", @@ -1387,7 +1391,7 @@ var _GpfError = gpf.Error = function () { }; _GpfError.prototype = new Error(); - _gpfExtend(_GpfError.prototype, /** @lends gpf.Error.prototype */ + Object.assign(_GpfError.prototype, /** @lends gpf.Error.prototype */ { constructor: _GpfError, /** @@ -1433,7 +1437,7 @@ this._buildMessage(context); } NewErrorClass.prototype = new _GpfError(); - _gpfExtend(NewErrorClass.prototype, { + Object.assign(NewErrorClass.prototype, { code: code, name: name, message: message @@ -1558,7 +1562,7 @@ * Extract function description * * @param {Function} functionToDescribe Function to describe - * @return {gpf.typedef.functionDescription} Function description + * @return {gpf.typedef._functionDescription} Function description * @since 0.1.6 */ function _gpfFunctionDescribe(functionToDescribe) { @@ -1588,7 +1592,7 @@ /** * Build function source from description * - * @param {gpf.typedef.functionDescription} functionDescription Function description + * @param {gpf.typedef._functionDescription} functionDescription Function description * @return {String} Function source * @since 0.1.6 */ @@ -1604,7 +1608,7 @@ /** * Build function from description and context * - * @param {gpf.typedef.functionDescription} functionDescription Function description + * @param {gpf.typedef._functionDescription} functionDescription Function description * @param {Object} [context] Function context * @return {Function} Function * @since 0.1.6 @@ -1754,13 +1758,13 @@ /*eslint-disable no-invalid-this*/ // bound through thisArg if (name.charAt(0) === "$") { - this._check$Property(name); + this._check$Property(name, value); } else { - this._checkProperty(name); + this._checkProperty(name, value); } /*jshint -W040*/ /*eslint-enable no-invalid-this*/ } - _gpfExtend(_GpfEntityDefinition.prototype, /** @lends _GpfEntityDefinition.prototype */ + Object.assign(_GpfEntityDefinition.prototype, /** @lends _GpfEntityDefinition.prototype */ { /** * Entity type (class...) @@ -1781,11 +1785,13 @@ * Check if the $ property is allowed * * @param {String} name $ Property name + * @param {*} value $ Property value * @see _GpfEntityDefinition.prototype._allowed$Properties * @throws {gpf.Error.InvalidEntity$Property} * @since 0.1.6 */ - _check$Property: function (name) { + _check$Property: function (name, value) { + _gpfIgnore(value); if (-1 === this._allowed$Properties.indexOf(name)) { gpf.Error.invalidEntity$Property(); } @@ -1795,9 +1801,13 @@ * NOTE: $ properties are handled by {@link _check$Property} * * @param {String} name Property name + * @param {*} value Property value * @since 0.1.6 */ - _checkProperty: _gpfFunc(["name"], " "), + _checkProperty: _gpfFunc([ + "name", + "value" + ], " "), /** * Check the properties contained in the definition passed to {@link gpf.define} * @since 0.1.6 @@ -1885,7 +1895,7 @@ this._checkNamespace(); } }); - _gpfExtend(_GpfEntityDefinition.prototype, /** @lends _GpfEntityDefinition.prototype */ + Object.assign(_GpfEntityDefinition.prototype, /** @lends _GpfEntityDefinition.prototype */ { /** * Instance builder function (a.k.a. public constructor) @@ -1932,7 +1942,7 @@ _GpfEntityDefinition.call(this, definition); /*eslint-enable no-invalid-this*/ } _GpfClassDefinition.prototype = Object.create(_GpfEntityDefinition.prototype); - _gpfExtend(_GpfClassDefinition.prototype, /** @lends _GpfClassDefinition.prototype */ + Object.assign(_GpfClassDefinition.prototype, /** @lends _GpfClassDefinition.prototype */ { constructor: _GpfClassDefinition, /** @@ -1975,7 +1985,33 @@ * $extend can be either a class or a string that must resolve to a class using {@see gpf.context} * @since 0.1.6 */ - invalidClassExtend: "Invalid class extend" + invalidClassExtend: "Invalid class extend", + /** + * ### Summary + * + * The class constructor must be a method + * + * ### Description + * + * The constructor member is a special one, see {@tutorial DEFINE} + * + * @see {@tutorial DEFINE} + * @since 0.1.7 + */ + invalidClassConstructor: "Invalid class constructor", + /** + * ### Summary + * + * A member override is changing the type + * + * ### Description + * + * The constructor member is a special one, see {@tutorial DEFINE} + * + * @see {@tutorial DEFINE} + * @since 0.1.7 + */ + invalidClassOverride: "Invalid class override" }); /** * If extend is a string, apply _gpfContext on it @@ -1990,7 +2026,7 @@ } return extend; } - _gpfExtend(_GpfClassDefinition.prototype, /** @lends _gpfClassDefinition.prototype */ + Object.assign(_GpfClassDefinition.prototype, /** @lends _gpfClassDefinition.prototype */ { /** * @inheritdoc @@ -2030,15 +2066,71 @@ gpf.Error.invalidClassProperty(); } }, + /** + * Check that the constructor is a method + * + * @param {*} constructorValue Value read from definition dictionary + * @throws {gpf.Error.InvalidClassConstructor} + * @since 0.1.7 + */ + _checkConstructorMember: function (constructorValue) { + if ("function" !== typeof constructorValue) { + gpf.Error.invalidClassConstructor(); + } + }, + /** + * Check if the value correspond to the overridden value + * + * @param {*} value Member value + * @param {*} overriddenValue Overridden member value + * @throws {gpf.Error.InvalidClassOverride} + * @since 0.1.7 + */ + _checkOverridenMember: function (value, overriddenValue) { + if (typeof value !== typeof overriddenValue) { + gpf.Error.invalidClassOverride(); + } + }, + /** + * Check if the member overrides an inherited one + * + * @param {String} name Member name + * @param {*} value Member value + * @throws {gpf.Error.InvalidClassOverride} + * @since 0.1.7 + */ + _checkIfOverriddenMember: function (name, value) { + var overriddenMember = this._extend.prototype[name]; + if (undefined !== overriddenMember) { + this._checkOverridenMember(value, overriddenMember); + } + }, + /** + * Check the value of the member: + * - If the member name is "constructor", it must be a function + * + * @param {String} name Property name + * @param {*} value Property value + * @private + * @since 0.1.7 + */ + _checkMemberValue: function (name, value) { + if ("constructor" === name) { + this._checkConstructorMember(value); + } else { + this._checkIfOverriddenMember(name, value); + } + }, /** * @inheritdoc * @throws {gpf.Error.InvalidClassProperty} * @since 0.1.6 */ - _checkProperty: function (name) { + _checkProperty: function (name, value) { _GpfEntityDefinition.prototype._checkProperty.call(this, name); this._checkMemberName(name); this._checkReservedMemberName(name); + this._checkMemberValue(name, value); }, /** * @inheritdoc @@ -2084,13 +2176,13 @@ * @since 0.1.6 */ check: function () { - _GpfEntityDefinition.prototype.check.call(this); this._readExtend(); this._checkExtend(); + _GpfEntityDefinition.prototype.check.call(this); } }); _gpfErrorDeclare("define/class/constructor", { "classConstructorFunction": "This is a class constructor function, use with new" }); - _gpfExtend(_GpfClassDefinition.prototype, /** @lends _GpfClassDefinition.prototype */ + Object.assign(_GpfClassDefinition.prototype, /** @lends _GpfClassDefinition.prototype */ { /** * Resolved constructor @@ -2100,6 +2192,20 @@ */ _resolvedConstructor: _gpfEmptyFunc }); + function _gpfDefineGetClassSecuredConstructorDefinition(classDefinition) { + var name = classDefinition._name; + return { + name: name, + parameters: _gpfFunctionDescribe(classDefinition._resolvedConstructor).parameters, + body: "if (!(this instanceof _classDef_._instanceBuilder)) gpf.Error.classConstructorFunction();\n" + "_classDef_._resolvedConstructor.apply(this, arguments);" + }; + } + function _gpfDefineGetClassSecuredConstructorContext(classDefinition) { + return { + gpf: gpf, + _classDef_: classDefinition + }; + } /** * Allocate a secured named constructor * @@ -2109,64 +2215,225 @@ * @since 0.1.6 */ function _gpfDefineGetClassSecuredConstructor(classDefinition) { - return _gpfFunctionBuild({ - name: classDefinition._name, - body: "if (!(this instanceof a._instanceBuilder)) $.Error.classConstructorFunction();\n" + "a._resolvedConstructor.apply(this, arguments);" - }, { - $: gpf, - a: classDefinition - }); + return _gpfFunctionBuild(_gpfDefineGetClassSecuredConstructorDefinition(classDefinition), _gpfDefineGetClassSecuredConstructorContext(classDefinition)); + } + _gpfErrorDeclare("define/class/super", { + /** + * ### Summary + * + * $super used in a member that doesn't override a method + * + * ### Description + * + * $super can't be used if the method does not override an inherited one + * @since 0.1.7 + */ + invalidClassSuper: "Invalid class super", + /** + * ### Summary + * + * An invalid member of $super was used + * + * ### Description + * + * $super members must point to a method exposed by the inherited prototype. + * @since 0.1.7 + */ + invalidClassSuperMember: "Invalid class super member" + }); + /** + * Used when $super points to a non existent member + * + * @throws {gpf.Error.InvalidClassSuper} + * @since 0.1.7 + */ + function _gpfClassNoSuper() { + gpf.Error.invalidClassSuper(); + } + /** + * Copy super method signature and invokes it. + * NOTE: it is required to create a new function as it will receive additional members + * + * @param {Function} superMethod Super method to copy + * @return {Function} New function that wraps the super method + * @since 0.1.7 + */ + function _gpfClassSuperCreateWithSameSignature(superMethod) { + var definition = _gpfFunctionDescribe(superMethod); + definition.body = "return _superMethod_.apply(this, arguments);"; + return _gpfFunctionBuild(definition, { _superMethod_: superMethod }); + } + /** + * Create $super function, either based on super method or triggering an error + * + * @param {*} superMember Member extracted from inherited prototype + * @return {Function} $super function + * @since 0.1.7 + */ + function _gpfClassSuperCreate(superMember) { + if ("function" !== typeof superMember) { + superMember = _gpfClassNoSuper; + } + return _gpfClassSuperCreateWithSameSignature(superMember); } - function _gpfClassMethodCreateSuperified(method, superMethod) { - // Keep signature - var description = _gpfFunctionDescribe(method); - description.body = "this.$super=s;" + "var r=m.apply(this,arguments);" + "delete this.$super;\n" + "return r;"; - return _gpfFunctionBuild(description, { - m: method, - s: superMethod + /** + * Copy super method signature and apply weak binding. + * + * @param {Object} that Object instance + * @param {Function} $super $super member + * @param {*} superMethod superMember Member extracted from inherited prototype + * @return {Function} $super method + * @since 0.1.7 + */ + function _gpfClassSuperCreateWeakBoundWithSameSignature(that, $super, superMethod) { + var definition = _gpfFunctionDescribe(superMethod); + definition.body = "return _superMethod_.apply(this === _$super_ ? _that_ : this, arguments);"; + return _gpfFunctionBuild(definition, { + _that_: that, + _$super_: $super, + _superMethod_: superMethod }); } - function _gpfClassMethodSuperifyIfNeeded(method, superMethod) { - if (new RegExp("\\.\\$super\\b").exec(method)) { - return _gpfClassMethodCreateSuperified(method, superMethod); + /** + * Create $super method + * NOTE: if the super method is not a function, an exception is thrown + * + * @param {Object} that Object instance + * @param {Function} $super $super member + * @param {*} superMethod superMember Member extracted from inherited prototype + * @return {Function} $super method + * @throws {gpf.Error.InvalidClassSuperMember} + * @since 0.1.7 + */ + function _gpfClassSuperCreateMember(that, $super, superMethod) { + if ("function" !== typeof superMethod) { + gpf.Error.invalidClassSuperMember(); } - return method; + return _gpfClassSuperCreateWeakBoundWithSameSignature(that, $super, superMethod); } /** - * Create a method that can use this.$super + * Extract all 'members' that are used on $super * - * @param {Function} method method to superify - * @param {Function} superMethod method to be called when this.$super is called - * @return {Function} Superified method - * @since 0.1.6 + * @param {Function} method Method to analyze + * @return {String[]} Member names that are used + * @since 0.1.7 */ - function _gpfClassMethodSuperify(method, superMethod) { - if (!superMethod) { - superMethod = _gpfEmptyFunc; + function _gpfClassMethodExtractSuperMembers(method) { + var re = new RegExp("\\.\\$super\\.(\\w+)\\b", "g"), match = re.exec(method), result = []; + while (match) { + result.push(match[1]); + match = re.exec(method); } - return _gpfClassMethodSuperifyIfNeeded(method, superMethod); + return result; } - _gpfExtend(_GpfClassDefinition.prototype, /** @lends _GpfClassDefinition.prototype */ + Object.assign(_GpfClassDefinition.prototype, /** @lends _GpfClassDefinition.prototype */ + { + /** + * Called before invoking a that contains $super method, it is responsible of allocating the $super object + * + * @param {Object} that Object instance + * @param {String} methodName Name of the method that uses $super + * @param {String[]} superMembers Expected member names on $super + * @return {Function} $super method + * @since 0.1.7 + */ + _get$Super: function (that, methodName, superMembers) { + var superProto = this._extend.prototype, $super = _gpfClassSuperCreate(superProto[methodName]); + superMembers.forEach(function (memberName) { + $super[memberName] = _gpfClassSuperCreateMember(that, $super, superProto[memberName]); + }); + return $super; + }, + /** + * Body of superified method + * @since 0.1.7 + */ + _superifiedBody: "var _super_;\n" + "if (this.hasOwnProperty(\"$super\")) {\n" + " _super_ = this.$super;\n" + "}\n" + "this.$super = _classDef_._get$Super(this, _methodName_, _superMembers_);\n" + "try{\n" + " var _result_ = _method_.apply(this, arguments);\n" + "} finally {\n" + " if (undefined === _super_) {\n" + " delete this.$super;\n" + " } else {\n" + " this.$super = _super_;\n" + " }\n" + "}\n" + "return _result_;", + /** + * Generates context for the superified method + * + * @param {Function} method Method to superify + * @param {String} methodName Name of the method (used to search in object prototype) + * @param {String[]} superMembers Detected $super members used in the method + * @return {Object} Context of superified method + * @since 0.1.7 + */ + _getSuperifiedContext: function (method, methodName, superMembers) { + return { + _method_: method, + _methodName_: methodName, + _superMembers_: superMembers, + _classDef_: this + }; + }, + /** + * Generates the superified version of the method + * + * @param {Function} method Method to superify + * @param {String} methodName Name of the method (used to search in object prototype) + * @param {String[]} superMembers Detected $super members used in the method + * @return {Function} Superified method + * @since 0.1.7 + */ + _createSuperified: function (method, methodName, superMembers) { + // Keep signature + var description = _gpfFunctionDescribe(method); + description.body = this._superifiedBody; + return _gpfFunctionBuild(description, this._getSuperifiedContext(method, methodName, superMembers)); + }, + /** + * Create a method that can use this.$super + * + * @param {Function} method Method to superify + * @param {String} methodName Name of the method (used to search in object prototype) + * @return {Function} Superified method + * @since 0.1.7 + */ + _superify: function (method, methodName) { + if (new RegExp("\\.\\$super\\b").exec(method)) { + return this._createSuperified(method, methodName, _gpfClassMethodExtractSuperMembers(method)); + } + return method; + } + }); + Object.assign(_GpfClassDefinition.prototype, /** @lends _GpfClassDefinition.prototype */ { /** * @inheritdoc * @since 0.1.6 */ _build: function () { - var newClass = _gpfDefineGetClassSecuredConstructor(this), - // Basic JavaScript inheritance mechanism: Defines the newClass prototype as an instance of the super class - newPrototype = Object.create(this._extend.prototype); + var newClass, newPrototype; + this._resolveConstructor(); + newClass = _gpfDefineGetClassSecuredConstructor(this); + // Basic JavaScript inheritance mechanism: Defines the newClass prototype as an instance of the super class + newPrototype = Object.create(this._extend.prototype); // Populate our constructed prototype object newClass.prototype = newPrototype; // Enforce the constructor to be what we expect newPrototype.constructor = newClass; this._buildPrototype(newPrototype); - this._resolveConstructor(); return newClass; }, + /** + * Add method to the new class prototype + * + * @param {Object} newPrototype New class prototype + * @param {String} methodName Method name + * @param {Function} method Method + * @since 0.1.7 + */ _addMethodToPrototype: function (newPrototype, methodName, method) { - newPrototype[methodName] = _gpfClassMethodSuperify(method, this._extend.prototype[methodName]); + newPrototype[methodName] = this._superify(method, methodName); }, + /** + * Add member to the new class prototype + * + * @param {Object} newPrototype New class prototype + * @param {String} memberName Member name + * @param {*} value Member value + * @since 0.1.7 + */ _addMemberToPrototype: function (newPrototype, memberName, value) { if ("function" === typeof value) { this._addMethodToPrototype(newPrototype, memberName, value); @@ -2174,6 +2441,12 @@ newPrototype[memberName] = value; } }, + /** + * Build the new class prototype + * + * @param {Object} newPrototype New class prototype + * @since 0.1.7 + */ _buildPrototype: function (newPrototype) { _gpfObjectForEach(this._initialDefinition, function (value, memberName) { if (memberName.charAt(0) !== "$" && memberName !== "constructor") { @@ -2181,14 +2454,27 @@ } }, this); }, + /** + * Set the inherited constructor if not Object + * @since 0.1.7 + */ + _setResolvedConstructorToInherited: function () { + if (this._extend !== Object) { + this._resolvedConstructor = this._extend; + } + }, + /** + * Assign the proper constructor to _resolvedConstructor + * @since 0.1.7 + */ _resolveConstructor: function () { if (this._initialDefinition.hasOwnProperty("constructor")) { /* jshint -W069*/ /*eslint-disable dot-notation*/ - this._resolvedConstructor = _gpfClassMethodSuperify(this._initialDefinition["constructor"], this._extend); /* jshint +W069*/ - /*eslint-enable dot-notation*/ + this._resolvedConstructor = this._superify(this._initialDefinition["constructor"], "constructor"); /* jshint +W069*/ + /*eslint-enable dot-notation*/ } else { - this._resolvedConstructor = this._extend; + this._setResolvedConstructorToInherited(); } } }); diff --git a/build/gpf-release.js b/build/gpf-release.js index 3172fc1f..e7d4ea6b 100644 --- a/build/gpf-release.js +++ b/build/gpf-release.js @@ -1,2 +1,2 @@ -(function(root,factory){"use strict";if(typeof define==="function"&&define.amd){define(["exports"],factory);}else if(typeof exports!=="undefined"){factory(exports);}else if(typeof module!=="undefined"&&module.exports){factory(module.exports);}else{var newGpf={};factory(newGpf);root.gpf=newGpf;}}(this,function(gpf){"use strict";function _gpfEmptyFunc(){}var _gpfVersion="0.1.6",_GPF_HOST={BROWSER:"browser",NODEJS:"nodejs",PHANTOMJS:"phantomjs",RHINO:"rhino",UNKNOWN:"unknown",WSCRIPT:"wscript"},_gpfHost=_GPF_HOST.UNKNOWN,_gpfDosPath=false,_gpfMainContext=this,_gpfIgnore=_gpfEmptyFunc,_gpfExit=_gpfEmptyFunc,_gpfWebWindow,_gpfWebDocument,_gpfWebHead,_gpfMsFSO,_gpfNodeFs,_gpfNodePath;if("undefined"!==typeof WScript){_gpfHost=_GPF_HOST.WSCRIPT;_gpfDosPath=true;}else if("undefined"!==typeof print&&"undefined"!==typeof java){_gpfHost=_GPF_HOST.RHINO;_gpfDosPath=false;}else if("undefined"!==typeof phantom&&phantom.version){_gpfHost=_GPF_HOST.PHANTOMJS;_gpfDosPath=require("fs").separator==="\\";_gpfMainContext=window;}else if("undefined"!==typeof module&&module.exports){_gpfHost=_GPF_HOST.NODEJS;_gpfNodePath=require("path");_gpfDosPath=_gpfNodePath.sep==="\\";_gpfMainContext=global;}else if("undefined"!==typeof window){_gpfHost=_GPF_HOST.BROWSER;_gpfMainContext=window;}gpf.hosts={browser:_GPF_HOST.BROWSER,nodejs:_GPF_HOST.NODEJS,phantomjs:_GPF_HOST.PHANTOMJS,rhino:_GPF_HOST.RHINO,unknown:_GPF_HOST.UNKNOWN,wscript:_GPF_HOST.WSCRIPT};gpf.host=function(){return _gpfHost;};gpf.version=function(){return _gpfVersion;};if(_GPF_HOST.BROWSER===_gpfHost){_gpfExit=function(code){window.location="https://arnaudbuchholz.github.io/gpf/exit.html?"+(code||0);};_gpfWebWindow=window;_gpfWebDocument=document;_gpfWebHead=_gpfWebDocument.getElementsByTagName("head")[0]||_gpfWebDocument.documentElement;}if(_GPF_HOST.NODEJS===_gpfHost){_gpfExit=function(code){process.exit(code);};}if(_GPF_HOST.PHANTOMJS===_gpfHost){_gpfExit=function(code){phantom.exit(code);};_gpfWebWindow=window;_gpfWebDocument=document;_gpfWebHead=_gpfWebDocument.getElementsByTagName("head")[0]||_gpfWebDocument.documentElement;}if(_GPF_HOST.RHINO===_gpfHost){_gpfMainContext.console={log:function(t){print(" "+t);},info:function(t){print("[?] "+t);},warn:function(t){print("/!\\ "+t);},error:function(t){print("(X) "+t);}};_gpfExit=function(code){java.lang.System.exit(code);};}if(_GPF_HOST.WSCRIPT===_gpfHost){_gpfMainContext.console={log:function(t){WScript.Echo(" "+t);},info:function(t){WScript.Echo("[?] "+t);},warn:function(t){WScript.Echo("/!\\ "+t);},error:function(t){WScript.Echo("(X) "+t);}};_gpfExit=function(code){WScript.Quit(code);};}var _gpfIsArrayLike=function(obj){return Array.isArray(obj);};if(_GPF_HOST.BROWSER===_gpfHost&&(_gpfWebWindow.HTMLCollection||_gpfWebWindow.NodeList)){_gpfIsArrayLike=function(obj){return Array.isArray(obj)||obj instanceof _gpfWebWindow.HTMLCollection||obj instanceof _gpfWebWindow.NodeList;};}gpf.isArrayLike=_gpfIsArrayLike;function _gpfArrayForEach(array,callback,thisArg){var index,length=array.length;for(index=0;index":">"};function _gpfInstallMissingMembers(on,members){_gpfObjectForEach(members,function(value,memberName){if(on[memberName]===undefined){on[memberName]=value;}});}function _gpfInstallCompatibleMethods(on,methods){if(methods){_gpfInstallMissingMembers(on.prototype,methods);}}function _gpfInstallCompatibleStatics(on,statics){if(statics){_gpfInstallMissingMembers(on,statics);}}function _gpfInstallCompatibility(typeName,description){var on=description.on;_gpfInstallCompatibleMethods(on,description.methods);_gpfInstallCompatibleStatics(on,description.statics);}function _gpfArrayBind(callback,thisArg){if(undefined!==thisArg){return callback.bind(thisArg);}return callback;}function _gpfArrayForEachOwn(array,callback){var len=array.length,idx=0;while(idx_gpfGenericFactory.length){_gpfGenericFactory=_gpfGenerateGenericFactory(parameters.length);}return _gpfGenericFactory.apply(Constructor,parameters);}function _pad(number){if(10>number){return"0"+number;}return number;}_gpfInstallCompatibility("Date",{on:Date,methods:{toISOString:function(){return this.getUTCFullYear()+"-"+_pad(this.getUTCMonth()+1)+"-"+_pad(this.getUTCDate())+"T"+_pad(this.getUTCHours())+":"+_pad(this.getUTCMinutes())+":"+_pad(this.getUTCSeconds())+"."+(this.getUTCMilliseconds()/1000).toFixed(3).slice(2,5)+"Z";}}});var _gpfISO8601RegExp=new RegExp("^([0-9][0-9][0-9][0-9])\\-([0-9][0-9])\\-([0-9][0-9])"+"(?:T([0-9][0-9])\\:([0-9][0-9])\\:([0-9][0-9])(?:\\.([0-9][0-9][0-9])Z)?)?$");function _gpfCheckDateArray(dateArray){if(dateArray[1]<12&&dateArray[2]<32&&dateArray[3]<24&&dateArray[4]<60&&dateArray[5]<60){return dateArray;}}function _gpfAddDatePartToArray(dateArray,datePart){if(datePart){dateArray.push(parseInt(datePart,10));}else{dateArray.push(0);}}function _gpfToDateArray(matchResult){var dateArray=[],len=matchResult.length,idx;for(idx=1;idxnow){_gpfSleep(timeoutItem.dt-now);}timeoutItem.cb();}}if("undefined"===typeof setTimeout){if(_GPF_HOST.WSCRIPT===_gpfHost){_gpfSleep=function(t){WScript.Sleep(t);};}else if(_GPF_HOST.RHINO===_gpfHost){_gpfSleep=java.lang.Thread.sleep;}else{console.warn("No implementation for setTimeout");}_gpfMainContext.setTimeout=_gpSetTimeoutPolyfill;_gpfMainContext.clearTimeout=_gpfClearTimeoutPolyfill;gpf.handleTimeout=_gpfHandleTimeout;}var _gpfJsonStringify,_gpfJsonParse;function _gpfPreprocessValueForJson(callback){return function(value,index){if("function"===typeof value){return;}callback(_gpfJsonStringifyPolyfill(value),index);};}function _gpfObject2Json(object){var isArray,results;isArray=object instanceof Array;results=[];if(isArray){_gpfArrayForEach(object,_gpfPreprocessValueForJson(function(value){results.push(value);}));return"["+results.join(",")+"]";}_gpfObjectForEach(object,_gpfPreprocessValueForJson(function(value,property){results.push(_gpfStringEscapeFor(property,"javascript")+":"+value);}));return"{"+results.join(",")+"}";}function _gpfJsonStringifyObject(object){return object.toString();}var _gpfJsonStringifyMapping={undefined:_gpfEmptyFunc,"function":_gpfEmptyFunc,number:_gpfJsonStringifyObject,"boolean":_gpfJsonStringifyObject,string:function(object){return _gpfStringEscapeFor(object,"javascript");},object:function(object){if(null===object){return"null";}return _gpfObject2Json(object);}};function _gpfJsonStringifyPolyfill(object){return _gpfJsonStringifyMapping[typeof object](object);}function _gpfJsonParsePolyfill(test){return _gpfFunc("return "+test)();}if("undefined"===typeof JSON){_gpfJsonStringify=_gpfJsonStringifyPolyfill;_gpfJsonParse=_gpfJsonParsePolyfill;_gpfMainContext.JSON={stringify:_gpfJsonStringify,parse:_gpfJsonParse};}else{_gpfJsonStringify=JSON.stringify;_gpfJsonParse=JSON.parse;}function _gpfGetObjectProperty(parent,name){if(undefined!==parent){return parent[name];}}function _gpfGetOrCreateObjectProperty(parent,name){var result=parent[name];if(undefined===result){result=parent[name]={};}return result;}function _gpfReduceContext(path,reducer){var rootContext;if(path[0]==="gpf"){rootContext=gpf;path=path.slice(1);}else{rootContext=_gpfMainContext;}return path.reduce(reducer,rootContext);}function _gpfContext(path,createMissingParts){var reducer;if(createMissingParts){reducer=_gpfGetOrCreateObjectProperty;}else{reducer=_gpfGetObjectProperty;}return _gpfReduceContext(path,reducer);}gpf.context=function(path){if(undefined===path){return _gpfMainContext;}return _gpfContext(path.split("."));};function _gpfAssign(value,memberName){this[memberName]=value;}function _gpfExtend(destination,source){_gpfIgnore(source);[].slice.call(arguments,1).forEach(function(nthSource){_gpfObjectForEach(nthSource,_gpfAssign,destination);});return destination;}gpf.extend=_gpfExtend;_gpfStringEscapes.html=_gpfExtend(_gpfStringEscapes.xml,{"à":"à","á":"á","è":"è","é":"é","ê":"ê"});var _GpfError=gpf.Error=function(){};_GpfError.prototype=new Error;_gpfExtend(_GpfError.prototype,{constructor:_GpfError,code:0,name:"Error",message:"",_buildMessage:function(context){var replacements;if(context){replacements={};_gpfObjectForEach(context,function(value,key){replacements["{"+key+"}"]=value.toString();});this.message=_gpfStringReplaceEx(this.message,replacements);}}});function _gpfErrorFactory(code,name,message){function NewErrorClass(context){this._buildMessage(context);}NewErrorClass.prototype=new _GpfError;_gpfExtend(NewErrorClass.prototype,{code:code,name:name,message:message});NewErrorClass.prototype.constructor=NewErrorClass;_GpfError[_gpfStringCapitalize(name)]=NewErrorClass;return function(context){throw new NewErrorClass(context);};}function _gpfGenenerateErrorFunction(code,name,message){var result=_gpfErrorFactory(code,name,message);result.CODE=code;result.NAME=name;result.MESSAGE=message;return result;}var _gpfLastErrorCode=0;function _gpfErrorDeclare(source,dictionary){_gpfIgnore(source);_gpfObjectForEach(dictionary,function(message,name){var code=++_gpfLastErrorCode;gpf.Error["CODE_"+name.toUpperCase()]=code;gpf.Error[name]=_gpfGenenerateErrorFunction(code,name,message);});}_gpfErrorDeclare("error",{notImplemented:"Not implemented",abstractMethod:"Abstract method",assertionFailed:"Assertion failed: {message}",invalidParameter:"Invalid parameter"});function _gpfStringTrim(that){return that.trim();}function _gpfFunctionDescribeName(functionToDescribe,resultDescription){var name=functionToDescribe.compatibleName();if(name){resultDescription.name=name;}}function _gpfFunctionDescribeParameters(functionToDescribe,functionSource,resultDescription){if(functionToDescribe.length){resultDescription.parameters=new RegExp("\\(\\s*(\\w+(?:\\s*,\\s*\\w+)*)\\s*\\)").exec(functionSource)[1].split(",").map(_gpfStringTrim);}}function _gpfFunctionDescribeBody(functionSource,resultDescription){var body=_gpfStringTrim(new RegExp("{((?:.*\\n)*.*)}").exec(functionSource)[1]);if(body){resultDescription.body=body;}}function _gpfFunctionDescribeSource(functionToDescribe,resultDescription){var source=_gpfEmptyFunc.toString.call(functionToDescribe).replace(_gpfJsCommentsRegExp,"");_gpfFunctionDescribeParameters(functionToDescribe,source,resultDescription);_gpfFunctionDescribeBody(source,resultDescription);}function _gpfFunctionDescribe(functionToDescribe){var result={};_gpfFunctionDescribeName(functionToDescribe,result);_gpfFunctionDescribeSource(functionToDescribe,result);return result;}function _gpfFunctionBuildSourceName(functionDescription){if(functionDescription.name){return" "+functionDescription.name;}return"";}function _gpfFunctionBuildSourceParameters(functionDescription){if(functionDescription.parameters){return functionDescription.parameters.join(", ");}return"";}function _gpfFunctionBuildSourceBody(functionDescription){if(functionDescription.body){return functionDescription.body.toString();}return"";}function _gpfFunctionBuildSource(functionDescription){return"function"+_gpfFunctionBuildSourceName(functionDescription)+"("+_gpfFunctionBuildSourceParameters(functionDescription)+") {\n\t\"use strict\"\n"+_gpfFunctionBuildSourceBody(functionDescription)+"\n}";}function _gpfFunctionBuildWithContext(functionSource,context){var parameterNames=Object.keys(context),parameterValues=parameterNames.map(function(name){return context[name];});return _gpfFunc(parameterNames,"return "+functionSource).apply(null,parameterValues);}function _gpfFunctionBuild(functionDescription,context){return _gpfFunctionBuildWithContext(_gpfFunctionBuildSource(functionDescription),context||{});}_gpfErrorDeclare("define/detect",{invalidEntityType:"Invalid entity type"});var _gpfDefineTypedBuilders={};function _gpfDefineRead$TypedProperties(definition){var ResultEntityBuilder;_gpfObjectForEach(_gpfDefineTypedBuilders,function(TypedEntityBuilder,type){if(definition["$"+type]){ResultEntityBuilder=TypedEntityBuilder;}});return ResultEntityBuilder;}function _gpfDefineCheck$TypeProperty(definition){var typedEntityBuilder=_gpfDefineTypedBuilders[definition.$type];if(undefined===typedEntityBuilder){gpf.Error.invalidEntityType();}return typedEntityBuilder;}function _gpfDefineBuildTypedEntity(definition){var EntityBuilder=_gpfDefineRead$TypedProperties(definition),entityDefinition;if(!EntityBuilder){EntityBuilder=_gpfDefineCheck$TypeProperty(definition);}entityDefinition=new EntityBuilder(definition);entityDefinition.check();return entityDefinition;}function _GpfEntityDefinition(definition){_gpfAssert(definition&&"object"===typeof definition,"Expected an entity definition");this._initialDefinition=definition;}_GpfEntityDefinition.prototype={constructor:_GpfEntityDefinition,_initialDefinition:{}};function _gpfDefineGenerate$Keys(names){return names.split(",").map(function(name){return"$"+name;});}_gpfErrorDeclare("define/check",{invalidEntity$Property:"Invalid entity $ property",missingEntityName:"Missing entity name",invalidEntityNamespace:"Invalid entity namespace"});function _gpfDefineEntityCheckNameIsNotEmpty(){if(!this._name){gpf.Error.missingEntityName();}}function _gpfDefineEntityCheckProperty(value,name){_gpfIgnore(value);if(name.charAt(0)==="$"){this._check$Property(name);}else{this._checkProperty(name);}}_gpfExtend(_GpfEntityDefinition.prototype,{_type:"",_allowed$Properties:_gpfDefineGenerate$Keys("type,name,namespace"),_check$Property:function(name){if(-1===this._allowed$Properties.indexOf(name)){gpf.Error.invalidEntity$Property();}},_checkProperty:_gpfFunc(["name"]," "),_checkProperties:function(){_gpfObjectForEach(this._initialDefinition,_gpfDefineEntityCheckProperty,this);},_name:"",_readName:function(){var definition=this._initialDefinition;this._name=definition["$"+this._type]||definition.$name;},_checkNameIsNotEmpty:_gpfDefineEntityCheckNameIsNotEmpty,_checkName:_gpfDefineEntityCheckNameIsNotEmpty,_namespace:"",_extractRelativeNamespaceFromName:function(){var parts=new RegExp("(.*)\\.([^\\.]+)$").exec(this._name);if(parts){this._name=parts[2];return parts[1];}},_readNamespace:function(){var namespaces=[this._initialDefinition.$namespace,this._extractRelativeNamespaceFromName()].filter(function(namespacePart){return namespacePart;});if(namespaces.length>0){this._namespace=namespaces.join(".");}},_checkNamespace:function(){if(!new RegExp("^(:?[a-z_$][a-zA-Z0-9]+(:?\\.[a-z_$][a-zA-Z0-9]+)*)?$").exec(this._namespace)){gpf.Error.invalidEntityNamespace();}},check:function(){this._checkProperties();this._readName();this._checkNameIsNotEmpty();this._readNamespace();this._checkName();this._checkNamespace();}});_gpfExtend(_GpfEntityDefinition.prototype,{_instanceBuilder:null,getInstanceBuilder:function(){if(!this._instanceBuilder){this._setInstanceBuilder(this._build());}return this._instanceBuilder;},_setInstanceBuilder:function(value){if(this._namespace){_gpfContext(this._namespace.split("."),true)[this._name]=value;}this._instanceBuilder=value;},_build:_gpfEmptyFunc});function _GpfClassDefinition(definition){_GpfEntityDefinition.call(this,definition);}_GpfClassDefinition.prototype=Object.create(_GpfEntityDefinition.prototype);_gpfExtend(_GpfClassDefinition.prototype,{constructor:_GpfClassDefinition,_type:"class"});_gpfDefineTypedBuilders["class"]=_GpfClassDefinition;_gpfErrorDeclare("define/class/check",{invalidClassName:"Invalid class name",invalidClassProperty:"Invalid class property",invalidClassExtend:"Invalid class extend"});function _gpfDefineClassDecontextifyExtend(extend){if("string"===typeof extend){return _gpfContext(extend.split("."));}return extend;}_gpfExtend(_GpfClassDefinition.prototype,{_allowed$Properties:_GpfEntityDefinition.prototype._allowed$Properties.concat(_gpfDefineGenerate$Keys("class,extend")),_checkMemberName:function(name){if(!new RegExp("^[a-z_][a-zA-Z0-9]*$").exec(name)){gpf.Error.invalidClassProperty();}},_reservedNames:"super,class,public,private,protected,static,mixin".split(","),_checkReservedMemberName:function(name){if(-1!==this._reservedNames.indexOf(name)){gpf.Error.invalidClassProperty();}},_checkProperty:function(name){_GpfEntityDefinition.prototype._checkProperty.call(this,name);this._checkMemberName(name);this._checkReservedMemberName(name);},_checkName:function(){_GpfEntityDefinition.prototype._checkName.call(this);if(!new RegExp("^[A-Z_$][a-zA-Z0-9]*$").exec(this._name)){gpf.Error.invalidClassName();}},_extend:Object,_readExtend:function(){var extend=_gpfDefineClassDecontextifyExtend(this._initialDefinition.$extend);if(extend){this._extend=extend;}},_checkExtend:function(){if("function"!==typeof this._extend){gpf.Error.invalidClassExtend();}},check:function(){_GpfEntityDefinition.prototype.check.call(this);this._readExtend();this._checkExtend();}});_gpfErrorDeclare("define/class/constructor",{"classConstructorFunction":"This is a class constructor function, use with new"});_gpfExtend(_GpfClassDefinition.prototype,{_resolvedConstructor:_gpfEmptyFunc});function _gpfDefineGetClassSecuredConstructor(classDefinition){return _gpfFunctionBuild({name:classDefinition._name,body:"if (!(this instanceof a._instanceBuilder)) $.Error.classConstructorFunction();\n"+"a._resolvedConstructor.apply(this, arguments);"},{$:gpf,a:classDefinition});}function _gpfClassMethodCreateSuperified(method,superMethod){var description=_gpfFunctionDescribe(method);description.body="this.$super=s;"+"var r=m.apply(this,arguments);"+"delete this.$super;\n"+"return r;";return _gpfFunctionBuild(description,{m:method,s:superMethod});}function _gpfClassMethodSuperifyIfNeeded(method,superMethod){if(new RegExp("\\.\\$super\\b").exec(method)){return _gpfClassMethodCreateSuperified(method,superMethod);}return method;}function _gpfClassMethodSuperify(method,superMethod){if(!superMethod){superMethod=_gpfEmptyFunc;}return _gpfClassMethodSuperifyIfNeeded(method,superMethod);}_gpfExtend(_GpfClassDefinition.prototype,{_build:function(){var newClass=_gpfDefineGetClassSecuredConstructor(this),newPrototype=Object.create(this._extend.prototype);newClass.prototype=newPrototype;newPrototype.constructor=newClass;this._buildPrototype(newPrototype);this._resolveConstructor();return newClass;},_addMethodToPrototype:function(newPrototype,methodName,method){newPrototype[methodName]=_gpfClassMethodSuperify(method,this._extend.prototype[methodName]);},_addMemberToPrototype:function(newPrototype,memberName,value){if("function"===typeof value){this._addMethodToPrototype(newPrototype,memberName,value);}else{newPrototype[memberName]=value;}},_buildPrototype:function(newPrototype){_gpfObjectForEach(this._initialDefinition,function(value,memberName){if(memberName.charAt(0)!=="$"&&memberName!=="constructor"){this._addMemberToPrototype(newPrototype,memberName,value);}},this);},_resolveConstructor:function(){if(this._initialDefinition.hasOwnProperty("constructor")){this._resolvedConstructor=_gpfClassMethodSuperify(this._initialDefinition["constructor"],this._extend);}else{this._resolvedConstructor=this._extend;}}});function _gpfDefine(definition){var entityDefinition=_gpfDefineBuildTypedEntity(definition);return entityDefinition.getInstanceBuilder();}gpf.define=_gpfDefine;})); \ No newline at end of file +(function(root,factory){"use strict";if(typeof define==="function"&&define.amd){define(["exports"],factory);}else if(typeof exports!=="undefined"){factory(exports);}else if(typeof module!=="undefined"&&module.exports){factory(module.exports);}else{var newGpf={};factory(newGpf);root.gpf=newGpf;}}(this,function(gpf){"use strict";function _gpfEmptyFunc(){}var _gpfVersion="0.1.7",_GPF_HOST={BROWSER:"browser",NODEJS:"nodejs",PHANTOMJS:"phantomjs",RHINO:"rhino",UNKNOWN:"unknown",WSCRIPT:"wscript"},_gpfHost=_GPF_HOST.UNKNOWN,_gpfDosPath=false,_gpfMainContext=this,_gpfIgnore=_gpfEmptyFunc,_gpfExit=_gpfEmptyFunc,_gpfWebWindow,_gpfWebDocument,_gpfWebHead,_gpfMsFSO,_gpfNodeFs,_gpfNodePath;if("undefined"!==typeof WScript){_gpfHost=_GPF_HOST.WSCRIPT;_gpfDosPath=true;}else if("undefined"!==typeof print&&"undefined"!==typeof java){_gpfHost=_GPF_HOST.RHINO;_gpfDosPath=false;}else if("undefined"!==typeof phantom&&phantom.version){_gpfHost=_GPF_HOST.PHANTOMJS;_gpfDosPath=require("fs").separator==="\\";_gpfMainContext=window;}else if("undefined"!==typeof module&&module.exports){_gpfHost=_GPF_HOST.NODEJS;_gpfNodePath=require("path");_gpfDosPath=_gpfNodePath.sep==="\\";_gpfMainContext=global;}else if("undefined"!==typeof window){_gpfHost=_GPF_HOST.BROWSER;_gpfMainContext=window;}gpf.hosts={browser:_GPF_HOST.BROWSER,nodejs:_GPF_HOST.NODEJS,phantomjs:_GPF_HOST.PHANTOMJS,rhino:_GPF_HOST.RHINO,unknown:_GPF_HOST.UNKNOWN,wscript:_GPF_HOST.WSCRIPT};gpf.host=function(){return _gpfHost;};gpf.version=function(){return _gpfVersion;};if(_GPF_HOST.BROWSER===_gpfHost){_gpfExit=function(code){window.location="https://arnaudbuchholz.github.io/gpf/exit.html?"+(code||0);};_gpfWebWindow=window;_gpfWebDocument=document;_gpfWebHead=_gpfWebDocument.getElementsByTagName("head")[0]||_gpfWebDocument.documentElement;}if(_GPF_HOST.NODEJS===_gpfHost){_gpfExit=function(code){process.exit(code);};}if(_GPF_HOST.PHANTOMJS===_gpfHost){_gpfExit=function(code){phantom.exit(code);};_gpfWebWindow=window;_gpfWebDocument=document;_gpfWebHead=_gpfWebDocument.getElementsByTagName("head")[0]||_gpfWebDocument.documentElement;}if(_GPF_HOST.RHINO===_gpfHost){_gpfMainContext.console={log:function(t){print(" "+t);},info:function(t){print("[?] "+t);},warn:function(t){print("/!\\ "+t);},error:function(t){print("(X) "+t);}};_gpfExit=function(code){java.lang.System.exit(code);};}if(_GPF_HOST.WSCRIPT===_gpfHost){_gpfMainContext.console={log:function(t){WScript.Echo(" "+t);},info:function(t){WScript.Echo("[?] "+t);},warn:function(t){WScript.Echo("/!\\ "+t);},error:function(t){WScript.Echo("(X) "+t);}};_gpfExit=function(code){WScript.Quit(code);};}var _gpfIsArrayLike=function(obj){return Array.isArray(obj);};if(_GPF_HOST.BROWSER===_gpfHost&&(_gpfWebWindow.HTMLCollection||_gpfWebWindow.NodeList)){_gpfIsArrayLike=function(obj){return Array.isArray(obj)||obj instanceof _gpfWebWindow.HTMLCollection||obj instanceof _gpfWebWindow.NodeList;};}gpf.isArrayLike=_gpfIsArrayLike;function _gpfArrayForEach(array,callback,thisArg){var index,length=array.length;for(index=0;index":">"};function _gpfInstallMissingMembers(on,members){_gpfObjectForEach(members,function(value,memberName){if(on[memberName]===undefined){on[memberName]=value;}});}function _gpfInstallCompatibleMethods(on,methods){if(methods){_gpfInstallMissingMembers(on.prototype,methods);}}function _gpfInstallCompatibleStatics(on,statics){if(statics){_gpfInstallMissingMembers(on,statics);}}function _gpfInstallCompatibility(typeName,description){var on=description.on;_gpfInstallCompatibleMethods(on,description.methods);_gpfInstallCompatibleStatics(on,description.statics);}function _gpfArrayBind(callback,thisArg){if(undefined!==thisArg){return callback.bind(thisArg);}return callback;}function _gpfArrayForEachOwn(array,callback){var len=array.length,idx=0;while(idx_gpfGenericFactory.length){_gpfGenericFactory=_gpfGenerateGenericFactory(parameters.length);}return _gpfGenericFactory.apply(Constructor,parameters);}function _pad(number){if(10>number){return"0"+number;}return number;}_gpfInstallCompatibility("Date",{on:Date,methods:{toISOString:function(){return this.getUTCFullYear()+"-"+_pad(this.getUTCMonth()+1)+"-"+_pad(this.getUTCDate())+"T"+_pad(this.getUTCHours())+":"+_pad(this.getUTCMinutes())+":"+_pad(this.getUTCSeconds())+"."+(this.getUTCMilliseconds()/1000).toFixed(3).slice(2,5)+"Z";}}});var _gpfISO8601RegExp=new RegExp("^([0-9][0-9][0-9][0-9])\\-([0-9][0-9])\\-([0-9][0-9])"+"(?:T([0-9][0-9])\\:([0-9][0-9])\\:([0-9][0-9])(?:\\.([0-9][0-9][0-9])Z)?)?$");function _gpfCheckDateArray(dateArray){if(dateArray[1]<12&&dateArray[2]<32&&dateArray[3]<24&&dateArray[4]<60&&dateArray[5]<60){return dateArray;}}function _gpfAddDatePartToArray(dateArray,datePart){if(datePart){dateArray.push(parseInt(datePart,10));}else{dateArray.push(0);}}function _gpfToDateArray(matchResult){var dateArray=[],len=matchResult.length,idx;for(idx=1;idxnow){_gpfSleep(timeoutItem.dt-now);}timeoutItem.cb();}}if("undefined"===typeof setTimeout){if(_GPF_HOST.WSCRIPT===_gpfHost){_gpfSleep=function(t){WScript.Sleep(t);};}else if(_GPF_HOST.RHINO===_gpfHost){_gpfSleep=java.lang.Thread.sleep;}else{console.warn("No implementation for setTimeout");}_gpfMainContext.setTimeout=_gpSetTimeoutPolyfill;_gpfMainContext.clearTimeout=_gpfClearTimeoutPolyfill;gpf.handleTimeout=_gpfHandleTimeout;}var _gpfJsonStringify,_gpfJsonParse;function _gpfPreprocessValueForJson(callback){return function(value,index){if("function"===typeof value){return;}callback(_gpfJsonStringifyPolyfill(value),index);};}function _gpfObject2Json(object){var isArray,results;isArray=object instanceof Array;results=[];if(isArray){_gpfArrayForEach(object,_gpfPreprocessValueForJson(function(value){results.push(value);}));return"["+results.join(",")+"]";}_gpfObjectForEach(object,_gpfPreprocessValueForJson(function(value,property){results.push(_gpfStringEscapeFor(property,"javascript")+":"+value);}));return"{"+results.join(",")+"}";}function _gpfJsonStringifyObject(object){return object.toString();}var _gpfJsonStringifyMapping={undefined:_gpfEmptyFunc,"function":_gpfEmptyFunc,number:_gpfJsonStringifyObject,"boolean":_gpfJsonStringifyObject,string:function(object){return _gpfStringEscapeFor(object,"javascript");},object:function(object){if(null===object){return"null";}return _gpfObject2Json(object);}};function _gpfJsonStringifyPolyfill(object){return _gpfJsonStringifyMapping[typeof object](object);}function _gpfJsonParsePolyfill(test){return _gpfFunc("return "+test)();}if("undefined"===typeof JSON){_gpfJsonStringify=_gpfJsonStringifyPolyfill;_gpfJsonParse=_gpfJsonParsePolyfill;_gpfMainContext.JSON={stringify:_gpfJsonStringify,parse:_gpfJsonParse};}else{_gpfJsonStringify=JSON.stringify;_gpfJsonParse=JSON.parse;}function _gpfGetObjectProperty(parent,name){if(undefined!==parent){return parent[name];}}function _gpfGetOrCreateObjectProperty(parent,name){var result=parent[name];if(undefined===result){result=parent[name]={};}return result;}function _gpfReduceContext(path,reducer){var rootContext;if(path[0]==="gpf"){rootContext=gpf;path=path.slice(1);}else{rootContext=_gpfMainContext;}return path.reduce(reducer,rootContext);}function _gpfContext(path,createMissingParts){var reducer;if(createMissingParts){reducer=_gpfGetOrCreateObjectProperty;}else{reducer=_gpfGetObjectProperty;}return _gpfReduceContext(path,reducer);}gpf.context=function(path){if(undefined===path){return _gpfMainContext;}return _gpfContext(path.split("."));};gpf.extend=Object.assign;_gpfStringEscapes.html=Object.assign({},_gpfStringEscapes.xml,{"à":"à","á":"á","è":"è","é":"é","ê":"ê"});var _GpfError=gpf.Error=function(){};_GpfError.prototype=new Error;Object.assign(_GpfError.prototype,{constructor:_GpfError,code:0,name:"Error",message:"",_buildMessage:function(context){var replacements;if(context){replacements={};_gpfObjectForEach(context,function(value,key){replacements["{"+key+"}"]=value.toString();});this.message=_gpfStringReplaceEx(this.message,replacements);}}});function _gpfErrorFactory(code,name,message){function NewErrorClass(context){this._buildMessage(context);}NewErrorClass.prototype=new _GpfError;Object.assign(NewErrorClass.prototype,{code:code,name:name,message:message});NewErrorClass.prototype.constructor=NewErrorClass;_GpfError[_gpfStringCapitalize(name)]=NewErrorClass;return function(context){throw new NewErrorClass(context);};}function _gpfGenenerateErrorFunction(code,name,message){var result=_gpfErrorFactory(code,name,message);result.CODE=code;result.NAME=name;result.MESSAGE=message;return result;}var _gpfLastErrorCode=0;function _gpfErrorDeclare(source,dictionary){_gpfIgnore(source);_gpfObjectForEach(dictionary,function(message,name){var code=++_gpfLastErrorCode;gpf.Error["CODE_"+name.toUpperCase()]=code;gpf.Error[name]=_gpfGenenerateErrorFunction(code,name,message);});}_gpfErrorDeclare("error",{notImplemented:"Not implemented",abstractMethod:"Abstract method",assertionFailed:"Assertion failed: {message}",invalidParameter:"Invalid parameter"});function _gpfStringTrim(that){return that.trim();}function _gpfFunctionDescribeName(functionToDescribe,resultDescription){var name=functionToDescribe.compatibleName();if(name){resultDescription.name=name;}}function _gpfFunctionDescribeParameters(functionToDescribe,functionSource,resultDescription){if(functionToDescribe.length){resultDescription.parameters=new RegExp("\\(\\s*(\\w+(?:\\s*,\\s*\\w+)*)\\s*\\)").exec(functionSource)[1].split(",").map(_gpfStringTrim);}}function _gpfFunctionDescribeBody(functionSource,resultDescription){var body=_gpfStringTrim(new RegExp("{((?:.*\\n)*.*)}").exec(functionSource)[1]);if(body){resultDescription.body=body;}}function _gpfFunctionDescribeSource(functionToDescribe,resultDescription){var source=_gpfEmptyFunc.toString.call(functionToDescribe).replace(_gpfJsCommentsRegExp,"");_gpfFunctionDescribeParameters(functionToDescribe,source,resultDescription);_gpfFunctionDescribeBody(source,resultDescription);}function _gpfFunctionDescribe(functionToDescribe){var result={};_gpfFunctionDescribeName(functionToDescribe,result);_gpfFunctionDescribeSource(functionToDescribe,result);return result;}function _gpfFunctionBuildSourceName(functionDescription){if(functionDescription.name){return" "+functionDescription.name;}return"";}function _gpfFunctionBuildSourceParameters(functionDescription){if(functionDescription.parameters){return functionDescription.parameters.join(", ");}return"";}function _gpfFunctionBuildSourceBody(functionDescription){if(functionDescription.body){return functionDescription.body.toString();}return"";}function _gpfFunctionBuildSource(functionDescription){return"function"+_gpfFunctionBuildSourceName(functionDescription)+"("+_gpfFunctionBuildSourceParameters(functionDescription)+") {\n\t\"use strict\"\n"+_gpfFunctionBuildSourceBody(functionDescription)+"\n}";}function _gpfFunctionBuildWithContext(functionSource,context){var parameterNames=Object.keys(context),parameterValues=parameterNames.map(function(name){return context[name];});return _gpfFunc(parameterNames,"return "+functionSource).apply(null,parameterValues);}function _gpfFunctionBuild(functionDescription,context){return _gpfFunctionBuildWithContext(_gpfFunctionBuildSource(functionDescription),context||{});}_gpfErrorDeclare("define/detect",{invalidEntityType:"Invalid entity type"});var _gpfDefineTypedBuilders={};function _gpfDefineRead$TypedProperties(definition){var ResultEntityBuilder;_gpfObjectForEach(_gpfDefineTypedBuilders,function(TypedEntityBuilder,type){if(definition["$"+type]){ResultEntityBuilder=TypedEntityBuilder;}});return ResultEntityBuilder;}function _gpfDefineCheck$TypeProperty(definition){var typedEntityBuilder=_gpfDefineTypedBuilders[definition.$type];if(undefined===typedEntityBuilder){gpf.Error.invalidEntityType();}return typedEntityBuilder;}function _gpfDefineBuildTypedEntity(definition){var EntityBuilder=_gpfDefineRead$TypedProperties(definition),entityDefinition;if(!EntityBuilder){EntityBuilder=_gpfDefineCheck$TypeProperty(definition);}entityDefinition=new EntityBuilder(definition);entityDefinition.check();return entityDefinition;}function _GpfEntityDefinition(definition){_gpfAssert(definition&&"object"===typeof definition,"Expected an entity definition");this._initialDefinition=definition;}_GpfEntityDefinition.prototype={constructor:_GpfEntityDefinition,_initialDefinition:{}};function _gpfDefineGenerate$Keys(names){return names.split(",").map(function(name){return"$"+name;});}_gpfErrorDeclare("define/check",{invalidEntity$Property:"Invalid entity $ property",missingEntityName:"Missing entity name",invalidEntityNamespace:"Invalid entity namespace"});function _gpfDefineEntityCheckNameIsNotEmpty(){if(!this._name){gpf.Error.missingEntityName();}}function _gpfDefineEntityCheckProperty(value,name){_gpfIgnore(value);if(name.charAt(0)==="$"){this._check$Property(name,value);}else{this._checkProperty(name,value);}}Object.assign(_GpfEntityDefinition.prototype,{_type:"",_allowed$Properties:_gpfDefineGenerate$Keys("type,name,namespace"),_check$Property:function(name,value){_gpfIgnore(value);if(-1===this._allowed$Properties.indexOf(name)){gpf.Error.invalidEntity$Property();}},_checkProperty:_gpfFunc(["name","value"]," "),_checkProperties:function(){_gpfObjectForEach(this._initialDefinition,_gpfDefineEntityCheckProperty,this);},_name:"",_readName:function(){var definition=this._initialDefinition;this._name=definition["$"+this._type]||definition.$name;},_checkNameIsNotEmpty:_gpfDefineEntityCheckNameIsNotEmpty,_checkName:_gpfDefineEntityCheckNameIsNotEmpty,_namespace:"",_extractRelativeNamespaceFromName:function(){var parts=new RegExp("(.*)\\.([^\\.]+)$").exec(this._name);if(parts){this._name=parts[2];return parts[1];}},_readNamespace:function(){var namespaces=[this._initialDefinition.$namespace,this._extractRelativeNamespaceFromName()].filter(function(namespacePart){return namespacePart;});if(namespaces.length>0){this._namespace=namespaces.join(".");}},_checkNamespace:function(){if(!new RegExp("^(:?[a-z_$][a-zA-Z0-9]+(:?\\.[a-z_$][a-zA-Z0-9]+)*)?$").exec(this._namespace)){gpf.Error.invalidEntityNamespace();}},check:function(){this._checkProperties();this._readName();this._checkNameIsNotEmpty();this._readNamespace();this._checkName();this._checkNamespace();}});Object.assign(_GpfEntityDefinition.prototype,{_instanceBuilder:null,getInstanceBuilder:function(){if(!this._instanceBuilder){this._setInstanceBuilder(this._build());}return this._instanceBuilder;},_setInstanceBuilder:function(value){if(this._namespace){_gpfContext(this._namespace.split("."),true)[this._name]=value;}this._instanceBuilder=value;},_build:_gpfEmptyFunc});function _GpfClassDefinition(definition){_GpfEntityDefinition.call(this,definition);}_GpfClassDefinition.prototype=Object.create(_GpfEntityDefinition.prototype);Object.assign(_GpfClassDefinition.prototype,{constructor:_GpfClassDefinition,_type:"class"});_gpfDefineTypedBuilders["class"]=_GpfClassDefinition;_gpfErrorDeclare("define/class/check",{invalidClassName:"Invalid class name",invalidClassProperty:"Invalid class property",invalidClassExtend:"Invalid class extend",invalidClassConstructor:"Invalid class constructor",invalidClassOverride:"Invalid class override"});function _gpfDefineClassDecontextifyExtend(extend){if("string"===typeof extend){return _gpfContext(extend.split("."));}return extend;}Object.assign(_GpfClassDefinition.prototype,{_allowed$Properties:_GpfEntityDefinition.prototype._allowed$Properties.concat(_gpfDefineGenerate$Keys("class,extend")),_checkMemberName:function(name){if(!new RegExp("^[a-z_][a-zA-Z0-9]*$").exec(name)){gpf.Error.invalidClassProperty();}},_reservedNames:"super,class,public,private,protected,static,mixin".split(","),_checkReservedMemberName:function(name){if(-1!==this._reservedNames.indexOf(name)){gpf.Error.invalidClassProperty();}},_checkConstructorMember:function(constructorValue){if("function"!==typeof constructorValue){gpf.Error.invalidClassConstructor();}},_checkOverridenMember:function(value,overriddenValue){if(typeof value!==typeof overriddenValue){gpf.Error.invalidClassOverride();}},_checkIfOverriddenMember:function(name,value){var overriddenMember=this._extend.prototype[name];if(undefined!==overriddenMember){this._checkOverridenMember(value,overriddenMember);}},_checkMemberValue:function(name,value){if("constructor"===name){this._checkConstructorMember(value);}else{this._checkIfOverriddenMember(name,value);}},_checkProperty:function(name,value){_GpfEntityDefinition.prototype._checkProperty.call(this,name);this._checkMemberName(name);this._checkReservedMemberName(name);this._checkMemberValue(name,value);},_checkName:function(){_GpfEntityDefinition.prototype._checkName.call(this);if(!new RegExp("^[A-Z_$][a-zA-Z0-9]*$").exec(this._name)){gpf.Error.invalidClassName();}},_extend:Object,_readExtend:function(){var extend=_gpfDefineClassDecontextifyExtend(this._initialDefinition.$extend);if(extend){this._extend=extend;}},_checkExtend:function(){if("function"!==typeof this._extend){gpf.Error.invalidClassExtend();}},check:function(){this._readExtend();this._checkExtend();_GpfEntityDefinition.prototype.check.call(this);}});_gpfErrorDeclare("define/class/constructor",{"classConstructorFunction":"This is a class constructor function, use with new"});Object.assign(_GpfClassDefinition.prototype,{_resolvedConstructor:_gpfEmptyFunc});function _gpfDefineGetClassSecuredConstructorDefinition(classDefinition){var name=classDefinition._name;return{name:name,parameters:_gpfFunctionDescribe(classDefinition._resolvedConstructor).parameters,body:"if (!(this instanceof _classDef_._instanceBuilder)) gpf.Error.classConstructorFunction();\n"+"_classDef_._resolvedConstructor.apply(this, arguments);"};}function _gpfDefineGetClassSecuredConstructorContext(classDefinition){return{gpf:gpf,_classDef_:classDefinition};}function _gpfDefineGetClassSecuredConstructor(classDefinition){return _gpfFunctionBuild(_gpfDefineGetClassSecuredConstructorDefinition(classDefinition),_gpfDefineGetClassSecuredConstructorContext(classDefinition));}_gpfErrorDeclare("define/class/super",{invalidClassSuper:"Invalid class super",invalidClassSuperMember:"Invalid class super member"});function _gpfClassNoSuper(){gpf.Error.invalidClassSuper();}function _gpfClassSuperCreateWithSameSignature(superMethod){var definition=_gpfFunctionDescribe(superMethod);definition.body="return _superMethod_.apply(this, arguments);";return _gpfFunctionBuild(definition,{_superMethod_:superMethod});}function _gpfClassSuperCreate(superMember){if("function"!==typeof superMember){superMember=_gpfClassNoSuper;}return _gpfClassSuperCreateWithSameSignature(superMember);}function _gpfClassSuperCreateWeakBoundWithSameSignature(that,$super,superMethod){var definition=_gpfFunctionDescribe(superMethod);definition.body="return _superMethod_.apply(this === _$super_ ? _that_ : this, arguments);";return _gpfFunctionBuild(definition,{_that_:that,_$super_:$super,_superMethod_:superMethod});}function _gpfClassSuperCreateMember(that,$super,superMethod){if("function"!==typeof superMethod){gpf.Error.invalidClassSuperMember();}return _gpfClassSuperCreateWeakBoundWithSameSignature(that,$super,superMethod);}function _gpfClassMethodExtractSuperMembers(method){var re=new RegExp("\\.\\$super\\.(\\w+)\\b","g"),match=re.exec(method),result=[];while(match){result.push(match[1]);match=re.exec(method);}return result;}Object.assign(_GpfClassDefinition.prototype,{_get$Super:function(that,methodName,superMembers){var superProto=this._extend.prototype,$super=_gpfClassSuperCreate(superProto[methodName]);superMembers.forEach(function(memberName){$super[memberName]=_gpfClassSuperCreateMember(that,$super,superProto[memberName]);});return $super;},_superifiedBody:"var _super_;\n"+"if (this.hasOwnProperty(\"$super\")) {\n"+" _super_ = this.$super;\n"+"}\n"+"this.$super = _classDef_._get$Super(this, _methodName_, _superMembers_);\n"+"try{\n"+" var _result_ = _method_.apply(this, arguments);\n"+"} finally {\n"+" if (undefined === _super_) {\n"+" delete this.$super;\n"+" } else {\n"+" this.$super = _super_;\n"+" }\n"+"}\n"+"return _result_;",_getSuperifiedContext:function(method,methodName,superMembers){return{_method_:method,_methodName_:methodName,_superMembers_:superMembers,_classDef_:this};},_createSuperified:function(method,methodName,superMembers){var description=_gpfFunctionDescribe(method);description.body=this._superifiedBody;return _gpfFunctionBuild(description,this._getSuperifiedContext(method,methodName,superMembers));},_superify:function(method,methodName){if(new RegExp("\\.\\$super\\b").exec(method)){return this._createSuperified(method,methodName,_gpfClassMethodExtractSuperMembers(method));}return method;}});Object.assign(_GpfClassDefinition.prototype,{_build:function(){var newClass,newPrototype;this._resolveConstructor();newClass=_gpfDefineGetClassSecuredConstructor(this);newPrototype=Object.create(this._extend.prototype);newClass.prototype=newPrototype;newPrototype.constructor=newClass;this._buildPrototype(newPrototype);return newClass;},_addMethodToPrototype:function(newPrototype,methodName,method){newPrototype[methodName]=this._superify(method,methodName);},_addMemberToPrototype:function(newPrototype,memberName,value){if("function"===typeof value){this._addMethodToPrototype(newPrototype,memberName,value);}else{newPrototype[memberName]=value;}},_buildPrototype:function(newPrototype){_gpfObjectForEach(this._initialDefinition,function(value,memberName){if(memberName.charAt(0)!=="$"&&memberName!=="constructor"){this._addMemberToPrototype(newPrototype,memberName,value);}},this);},_setResolvedConstructorToInherited:function(){if(this._extend!==Object){this._resolvedConstructor=this._extend;}},_resolveConstructor:function(){if(this._initialDefinition.hasOwnProperty("constructor")){this._resolvedConstructor=this._superify(this._initialDefinition["constructor"],"constructor");}else{this._setResolvedConstructorToInherited();}}});function _gpfDefine(definition){var entityDefinition=_gpfDefineBuildTypedEntity(definition);return entityDefinition.getInstanceBuilder();}gpf.define=_gpfDefine;})); \ No newline at end of file diff --git a/build/gpf.js b/build/gpf.js index 38ecd3e5..1c6c13c6 100644 --- a/build/gpf.js +++ b/build/gpf.js @@ -1 +1 @@ -!function(a,b){"use strict";if("function"==typeof define&&define.amd)define(["exports"],b);else if("undefined"!=typeof exports)b(exports);else if("undefined"!=typeof module&&module.exports)b(module.exports);else{var c={};b(c),a.gpf=c}}(this,function(a){"use strict";function b(){}function c(a,b,c){var d,e=a.length;for(d=0;dZa.length&&(Za=B(b.length)),Za.apply(a,b)}function D(a){return 10>a?"0"+a:a}function E(a){if(a[1]<12&&a[2]<32&&a[3]<24&&a[4]<60&&a[5]<60)return a}function F(a,b){b?a.push(parseInt(b,10)):a.push(0)}function G(a){var b,c=[],d=a.length;for(b=1;bb&&fb(a.dt-b),a.cb()}function X(a){return function(b,c){"function"!=typeof b&&a($(b),c)}}function Y(a){var b,e;return b=a instanceof Array,e=[],b?(c(a,X(function(a){e.push(a)})),"["+e.join(",")+"]"):(d(a,X(function(a,b){e.push(n(b,"javascript")+":"+a)})),"{"+e.join(",")+"}")}function Z(a){return a.toString()}function $(a){return ib[typeof a](a)}function _(a){return j("return "+a)()}function aa(a,b){if(void 0!==a)return a[b]}function ba(a,b){var c=a[b];return void 0===c&&(c=a[b]={}),c}function ca(b,c){var d;return"gpf"===b[0]?(d=a,b=b.slice(1)):d=Ra,b.reduce(c,d)}function da(a,b){var c;return c=b?ba:aa,ca(a,c)}function ea(a,b){this[b]=a}function fa(a,b){return Sa(b),[].slice.call(arguments,1).forEach(function(b){d(b,ea,a)}),a}function ga(a,b,c){function d(a){this._buildMessage(a)}return d.prototype=new jb,fa(d.prototype,{code:a,name:b,message:c}),d.prototype.constructor=d,jb[k(b)]=d,function(a){throw new d(a)}}function ha(a,b,c){var d=ga(a,b,c);return d.CODE=a,d.NAME=b,d.MESSAGE=c,d}function ia(b,c){Sa(b),d(c,function(b,c){var d=++kb;a.Error["CODE_"+c.toUpperCase()]=d,a.Error[c]=ha(d,c,b)})}function ja(a){return a.trim()}function ka(a,b){var c=a.compatibleName();c&&(b.name=c)}function la(a,b,c){a.length&&(c.parameters=new RegExp("\\(\\s*(\\w+(?:\\s*,\\s*\\w+)*)\\s*\\)").exec(b)[1].split(",").map(ja))}function ma(a,b){var c=ja(new RegExp("{((?:.*\\n)*.*)}").exec(a)[1]);c&&(b.body=c)}function na(a,c){var d=b.toString.call(a).replace(bb,"");la(a,d,c),ma(d,c)}function oa(a){var b={};return ka(a,b),na(a,b),b}function pa(a){return a.name?" "+a.name:""}function qa(a){return a.parameters?a.parameters.join(", "):""}function ra(a){return a.body?a.body.toString():""}function sa(a){return"function"+pa(a)+"("+qa(a)+') {\n\t"use strict"\n'+ra(a)+"\n}"}function ta(a,b){var c=Object.keys(b),d=c.map(function(a){return b[a]});return j(c,"return "+a).apply(null,d)}function ua(a,b){return ta(sa(a),b||{})}function va(a){var b;return d(lb,function(c,d){a["$"+d]&&(b=c)}),b}function wa(b){var c=lb[b.$type];return void 0===c&&a.Error.invalidEntityType(),c}function xa(a){var b,c=va(a);return c||(c=wa(a)),b=new c(a),b.check(),b}function ya(a){Va(a&&"object"==typeof a,"Expected an entity definition"),this._initialDefinition=a}function za(a){return a.split(",").map(function(a){return"$"+a})}function Aa(){this._name||a.Error.missingEntityName()}function Ba(a,b){Sa(a),"$"===b.charAt(0)?this._check$Property(b):this._checkProperty(b)}function Ca(a){ya.call(this,a)}function Da(a){return"string"==typeof a?da(a.split(".")):a}function Ea(b){return ua({name:b._name,body:"if (!(this instanceof a._instanceBuilder)) $.Error.classConstructorFunction();\na._resolvedConstructor.apply(this, arguments);"},{$:a,a:b})}function Fa(a,b){var c=oa(a);return c.body="this.$super=s;var r=m.apply(this,arguments);delete this.$super;\nreturn r;",ua(c,{m:a,s:b})}function Ga(a,b){return new RegExp("\\.\\$super\\b").exec(a)?Fa(a,b):a}function Ha(a,c){return c||(c=b),Ga(a,c)}function Ia(a){var b=xa(a);return b.getInstanceBuilder()}var Ja,Ka,La,Ma,Na="0.1.6",Oa={BROWSER:"browser",NODEJS:"nodejs",PHANTOMJS:"phantomjs",RHINO:"rhino",UNKNOWN:"unknown",WSCRIPT:"wscript"},Pa=Oa.UNKNOWN,Qa=!1,Ra=this,Sa=b,Ta=b;"undefined"!=typeof WScript?(Pa=Oa.WSCRIPT,Qa=!0):"undefined"!=typeof print&&"undefined"!=typeof java?(Pa=Oa.RHINO,Qa=!1):"undefined"!=typeof phantom&&phantom.version?(Pa=Oa.PHANTOMJS,Qa="\\"===require("fs").separator,Ra=window):"undefined"!=typeof module&&module.exports?(Pa=Oa.NODEJS,Ma=require("path"),Qa="\\"===Ma.sep,Ra=global):"undefined"!=typeof window&&(Pa=Oa.BROWSER,Ra=window),a.hosts={browser:Oa.BROWSER,nodejs:Oa.NODEJS,phantomjs:Oa.PHANTOMJS,rhino:Oa.RHINO,unknown:Oa.UNKNOWN,wscript:Oa.WSCRIPT},a.host=function(){return Pa},a.version=function(){return Na},Oa.BROWSER===Pa&&(Ta=function(a){window.location="https://arnaudbuchholz.github.io/gpf/exit.html?"+(a||0)},Ja=window,Ka=document,La=Ka.getElementsByTagName("head")[0]||Ka.documentElement),Oa.NODEJS===Pa&&(Ta=function(a){process.exit(a)}),Oa.PHANTOMJS===Pa&&(Ta=function(a){phantom.exit(a)},Ja=window,Ka=document,La=Ka.getElementsByTagName("head")[0]||Ka.documentElement),Oa.RHINO===Pa&&(Ra.console={log:function(a){print(" "+a)},info:function(a){print("[?] "+a)},warn:function(a){print("/!\\ "+a)},error:function(a){print("(X) "+a)}},Ta=function(a){java.lang.System.exit(a)}),Oa.WSCRIPT===Pa&&(Ra.console={log:function(a){WScript.Echo(" "+a)},info:function(a){WScript.Echo("[?] "+a)},warn:function(a){WScript.Echo("/!\\ "+a)},error:function(a){WScript.Echo("(X) "+a)}},Ta=function(a){WScript.Quit(a)});var Ua=function(a){return Array.isArray(a)};Oa.BROWSER===Pa&&(Ja.HTMLCollection||Ja.NodeList)&&(Ua=function(a){return Array.isArray(a)||a instanceof Ja.HTMLCollection||a instanceof Ja.NodeList}),a.isArrayLike=Ua,a.forEach=function(a,b,e){return Ua(a)?void c(a,b,e):void d(a,b,e)};var Va,Wa;a.assert=f,a.asserts=g,Va=b,Wa=b;var Xa=Function;"break,case,class,catch,const,continue,debugger,default,delete,do,else,export,extends,finally,for,function,if,import,in,instanceof,let,new,return,super,switch,this,throw,try,typeof,var,void,while,with,yield".split(",");Oa.NODEJS===Pa&&(a.node={}),a.web={};var Ya={};Ya.javascript={"\\":"\\\\",'"':'\\"',"\n":"\\n","\r":"\\r","\t":"\\t"},Ya.xml={"&":"&","<":"<",">":">"},r("Array",{on:Array,methods:{every:function(a){return v(this,s(a,arguments[1]))},filter:function(a){var b=[];return a=s(a,arguments[1]),t(this,function(c,d,e){a(c,d,e)&&b.push(c)}),b},forEach:function(a){t(this,s(a,arguments[1]))},indexOf:function(a){var b=-1;return u(this,function(c,d){return c!==a||(b=d,!1)},arguments[1]||0),b},map:function(a){var b=new Array(this.length);return a=s(a,arguments[1]),t(this,function(c,d,e){b[d]=a(c,d,e)}),b},some:function(a){return a=s(a,arguments[1]),!v(this,function(b,c,d){return!a(b,c,d)})},reduce:function(a){var b,c=arguments[1],d=this.length,e=0;for(b=void 0===c?this[e++]:c;e0&&(this._namespace=a.join("."))},_checkNamespace:function(){new RegExp("^(:?[a-z_$][a-zA-Z0-9]+(:?\\.[a-z_$][a-zA-Z0-9]+)*)?$").exec(this._namespace)||a.Error.invalidEntityNamespace()},check:function(){this._checkProperties(),this._readName(),this._checkNameIsNotEmpty(),this._readNamespace(),this._checkName(),this._checkNamespace()}}),fa(ya.prototype,{_instanceBuilder:null,getInstanceBuilder:function(){return this._instanceBuilder||this._setInstanceBuilder(this._build()),this._instanceBuilder},_setInstanceBuilder:function(a){this._namespace&&(da(this._namespace.split("."),!0)[this._name]=a),this._instanceBuilder=a},_build:b}),Ca.prototype=Object.create(ya.prototype),fa(Ca.prototype,{constructor:Ca,_type:"class"}),lb["class"]=Ca,ia("define/class/check",{invalidClassName:"Invalid class name",invalidClassProperty:"Invalid class property",invalidClassExtend:"Invalid class extend"}),fa(Ca.prototype,{_allowed$Properties:ya.prototype._allowed$Properties.concat(za("class,extend")),_checkMemberName:function(b){new RegExp("^[a-z_][a-zA-Z0-9]*$").exec(b)||a.Error.invalidClassProperty()},_reservedNames:"super,class,public,private,protected,static,mixin".split(","),_checkReservedMemberName:function(b){-1!==this._reservedNames.indexOf(b)&&a.Error.invalidClassProperty()},_checkProperty:function(a){ya.prototype._checkProperty.call(this,a),this._checkMemberName(a),this._checkReservedMemberName(a)},_checkName:function(){ya.prototype._checkName.call(this),new RegExp("^[A-Z_$][a-zA-Z0-9]*$").exec(this._name)||a.Error.invalidClassName()},_extend:Object,_readExtend:function(){var a=Da(this._initialDefinition.$extend);a&&(this._extend=a)},_checkExtend:function(){"function"!=typeof this._extend&&a.Error.invalidClassExtend()},check:function(){ya.prototype.check.call(this),this._readExtend(),this._checkExtend()}}),ia("define/class/constructor",{"classConstructorFunction":"This is a class constructor function, use with new"}),fa(Ca.prototype,{_resolvedConstructor:b}),fa(Ca.prototype,{_build:function(){var a=Ea(this),b=Object.create(this._extend.prototype);return a.prototype=b,b.constructor=a,this._buildPrototype(b),this._resolveConstructor(),a},_addMethodToPrototype:function(a,b,c){a[b]=Ha(c,this._extend.prototype[b])},_addMemberToPrototype:function(a,b,c){"function"==typeof c?this._addMethodToPrototype(a,b,c):a[b]=c},_buildPrototype:function(a){d(this._initialDefinition,function(b,c){"$"!==c.charAt(0)&&"constructor"!==c&&this._addMemberToPrototype(a,c,b)},this)},_resolveConstructor:function(){this._initialDefinition.hasOwnProperty("constructor")?this._resolvedConstructor=Ha(this._initialDefinition.constructor,this._extend):this._resolvedConstructor=this._extend}}),a.define=Ia}); \ No newline at end of file +!function(a,b){"use strict";if("function"==typeof define&&define.amd)define(["exports"],b);else if("undefined"!=typeof exports)b(exports);else if("undefined"!=typeof module&&module.exports)b(module.exports);else{var c={};b(c),a.gpf=c}}(this,function(a){"use strict";function b(){}function c(a,b,c){var d,e=a.length;for(d=0;ddb.length&&(db=C(b.length)),db.apply(a,b)}function E(a){return 10>a?"0"+a:a}function F(a){if(a[1]<12&&a[2]<32&&a[3]<24&&a[4]<60&&a[5]<60)return a}function G(a,b){b?a.push(parseInt(b,10)):a.push(0)}function H(a){var b,c=[],d=a.length;for(b=1;bb&&lb(a.dt-b),a.cb()}function Z(a){return function(b,c){"function"!=typeof b&&a(aa(b),c)}}function $(a){var b,d;return b=a instanceof Array,d=[],b?(c(a,Z(function(a){d.push(a)})),"["+d.join(",")+"]"):($a(a,Z(function(a,b){d.push(o(b,"javascript")+":"+a)})),"{"+d.join(",")+"}")}function _(a){return a.toString()}function aa(a){return ob[typeof a](a)}function ba(a){return k("return "+a)()}function ca(a,b){if(void 0!==a)return a[b]}function da(a,b){var c=a[b];return void 0===c&&(c=a[b]={}),c}function ea(b,c){var d;return"gpf"===b[0]?(d=a,b=b.slice(1)):d=Wa,b.reduce(c,d)}function fa(a,b){var c;return c=b?da:ca,ea(a,c)}function ga(a,b,c){function d(a){this._buildMessage(a)}return d.prototype=new pb,Object.assign(d.prototype,{code:a,name:b,message:c}),d.prototype.constructor=d,pb[l(b)]=d,function(a){throw new d(a)}}function ha(a,b,c){var d=ga(a,b,c);return d.CODE=a,d.NAME=b,d.MESSAGE=c,d}function ia(b,c){Xa(b),$a(c,function(b,c){var d=++qb;a.Error["CODE_"+c.toUpperCase()]=d,a.Error[c]=ha(d,c,b)})}function ja(a){return a.trim()}function ka(a,b){var c=a.compatibleName();c&&(b.name=c)}function la(a,b,c){a.length&&(c.parameters=/\(\s*(\w+(?:\s*,\s*\w+)*)\s*\)/.exec(b)[1].split(",").map(ja))}function ma(a,b){var c=ja(/{((?:.*\n)*.*)}/.exec(a)[1]);c&&(b.body=c)}function na(a,c){var d=b.toString.call(a).replace(hb,"");la(a,d,c),ma(d,c)}function oa(a){var b={};return ka(a,b),na(a,b),b}function pa(a){return a.name?" "+a.name:""}function qa(a){return a.parameters?a.parameters.join(", "):""}function ra(a){return a.body?a.body.toString():""}function sa(a){return"function"+pa(a)+"("+qa(a)+') {\n\t"use strict"\n'+ra(a)+"\n}"}function ta(a,b){var c=Object.keys(b),d=c.map(function(a){return b[a]});return k(c,"return "+a).apply(null,d)}function ua(a,b){return ta(sa(a),b||{})}function va(a){var b;return $a(rb,function(c,d){a["$"+d]&&(b=c)}),b}function wa(b){var c=rb[b.$type];return void 0===c&&a.Error.invalidEntityType(),c}function xa(a){var b,c=va(a);return c||(c=wa(a)),b=new c(a),b.check(),b}function ya(a){_a(a&&"object"==typeof a,"Expected an entity definition"),this._initialDefinition=a}function za(a){return a.split(",").map(function(a){return"$"+a})}function Aa(){this._name||a.Error.missingEntityName()}function Ba(a,b){Xa(a),"$"===b.charAt(0)?this._check$Property(b,a):this._checkProperty(b,a)}function Ca(a){ya.call(this,a)}function Da(a){return"string"==typeof a?fa(a.split(".")):a}function Ea(a){var b=a._name;return{name:b,parameters:oa(a._resolvedConstructor).parameters,body:"if (!(this instanceof _classDef_._instanceBuilder)) gpf.Error.classConstructorFunction();\n_classDef_._resolvedConstructor.apply(this, arguments);"}}function Fa(b){return{gpf:a,_classDef_:b}}function Ga(a){return ua(Ea(a),Fa(a))}function Ha(){a.Error.invalidClassSuper()}function Ia(a){var b=oa(a);return b.body="return _superMethod_.apply(this, arguments);",ua(b,{_superMethod_:a})}function Ja(a){return"function"!=typeof a&&(a=Ha),Ia(a)}function Ka(a,b,c){var d=oa(c);return d.body="return _superMethod_.apply(this === _$super_ ? _that_ : this, arguments);",ua(d,{_that_:a,_$super_:b,_superMethod_:c})}function La(b,c,d){return"function"!=typeof d&&a.Error.invalidClassSuperMember(),Ka(b,c,d)}function Ma(a){for(var b=/\.\$super\.(\w+)\b/g,c=b.exec(a),d=[];c;)d.push(c[1]),c=b.exec(a);return d}function Na(a){var b=xa(a);return b.getInstanceBuilder()}var Oa,Pa,Qa,Ra,Sa="0.1.7",Ta={BROWSER:"browser",NODEJS:"nodejs",PHANTOMJS:"phantomjs",RHINO:"rhino",UNKNOWN:"unknown",WSCRIPT:"wscript"},Ua=Ta.UNKNOWN,Va=!1,Wa=this,Xa=b,Ya=b;"undefined"!=typeof WScript?(Ua=Ta.WSCRIPT,Va=!0):"undefined"!=typeof print&&"undefined"!=typeof java?(Ua=Ta.RHINO,Va=!1):"undefined"!=typeof phantom&&phantom.version?(Ua=Ta.PHANTOMJS,Va="\\"===require("fs").separator,Wa=window):"undefined"!=typeof module&&module.exports?(Ua=Ta.NODEJS,Ra=require("path"),Va="\\"===Ra.sep,Wa=global):"undefined"!=typeof window&&(Ua=Ta.BROWSER,Wa=window),a.hosts={browser:Ta.BROWSER,nodejs:Ta.NODEJS,phantomjs:Ta.PHANTOMJS,rhino:Ta.RHINO,unknown:Ta.UNKNOWN,wscript:Ta.WSCRIPT},a.host=function(){return Ua},a.version=function(){return Sa},Ta.BROWSER===Ua&&(Ya=function(a){window.location="https://arnaudbuchholz.github.io/gpf/exit.html?"+(a||0)},Oa=window,Pa=document,Qa=Pa.getElementsByTagName("head")[0]||Pa.documentElement),Ta.NODEJS===Ua&&(Ya=function(a){process.exit(a)}),Ta.PHANTOMJS===Ua&&(Ya=function(a){phantom.exit(a)},Oa=window,Pa=document,Qa=Pa.getElementsByTagName("head")[0]||Pa.documentElement),Ta.RHINO===Ua&&(Wa.console={log:function(a){print(" "+a)},info:function(a){print("[?] "+a)},warn:function(a){print("/!\\ "+a)},error:function(a){print("(X) "+a)}},Ya=function(a){java.lang.System.exit(a)}),Ta.WSCRIPT===Ua&&(Wa.console={log:function(a){WScript.Echo(" "+a)},info:function(a){WScript.Echo("[?] "+a)},warn:function(a){WScript.Echo("/!\\ "+a)},error:function(a){WScript.Echo("(X) "+a)}},Ya=function(a){WScript.Quit(a)});var Za=function(a){return Array.isArray(a)};Ta.BROWSER===Ua&&(Oa.HTMLCollection||Oa.NodeList)&&(Za=function(a){return Array.isArray(a)||a instanceof Oa.HTMLCollection||a instanceof Oa.NodeList}),a.isArrayLike=Za;var $a;$a=Ta.WSCRIPT===Ua?e:d,a.forEach=function(a,b,d){return Za(a)?void c(a,b,d):void $a(a,b,d)};var _a,ab;a.assert=g,a.asserts=h,_a=b,ab=b;var bb=Function;"break,case,class,catch,const,continue,debugger,default,delete,do,else,export,extends,finally,for,function,if,import,in,instanceof,let,new,return,super,switch,this,throw,try,typeof,var,void,while,with,yield".split(",");Ta.NODEJS===Ua&&(a.node={}),a.web={};var cb={};cb.javascript={"\\":"\\\\",'"':'\\"',"\n":"\\n","\r":"\\r","\t":"\\t"},cb.xml={"&":"&","<":"<",">":">"},s("Array",{on:Array,methods:{every:function(a){return w(this,t(a,arguments[1]))},filter:function(a){var b=[];return a=t(a,arguments[1]),u(this,function(c,d,e){a(c,d,e)&&b.push(c)}),b},forEach:function(a){u(this,t(a,arguments[1]))},indexOf:function(a){var b=-1;return v(this,function(c,d){return c!==a||(b=d,!1)},arguments[1]||0),b},map:function(a){var b=new Array(this.length);return a=t(a,arguments[1]),u(this,function(c,d,e){b[d]=a(c,d,e)}),b},some:function(a){return a=t(a,arguments[1]),!w(this,function(b,c,d){return!a(b,c,d)})},reduce:function(a){var b,c=arguments[1],d=this.length,e=0;for(b=void 0===c?this[e++]:c;e0&&(this._namespace=a.join("."))},_checkNamespace:function(){/^(:?[a-z_$][a-zA-Z0-9]+(:?\.[a-z_$][a-zA-Z0-9]+)*)?$/.exec(this._namespace)||a.Error.invalidEntityNamespace()},check:function(){this._checkProperties(),this._readName(),this._checkNameIsNotEmpty(),this._readNamespace(),this._checkName(),this._checkNamespace()}}),Object.assign(ya.prototype,{_instanceBuilder:null,getInstanceBuilder:function(){return this._instanceBuilder||this._setInstanceBuilder(this._build()),this._instanceBuilder},_setInstanceBuilder:function(a){this._namespace&&(fa(this._namespace.split("."),!0)[this._name]=a),this._instanceBuilder=a},_build:b}),Ca.prototype=Object.create(ya.prototype),Object.assign(Ca.prototype,{constructor:Ca,_type:"class"}),rb["class"]=Ca,ia("define/class/check",{invalidClassName:"Invalid class name",invalidClassProperty:"Invalid class property",invalidClassExtend:"Invalid class extend",invalidClassConstructor:"Invalid class constructor",invalidClassOverride:"Invalid class override"}),Object.assign(Ca.prototype,{_allowed$Properties:ya.prototype._allowed$Properties.concat(za("class,extend")),_checkMemberName:function(b){/^[a-z_][a-zA-Z0-9]*$/.exec(b)||a.Error.invalidClassProperty()},_reservedNames:"super,class,public,private,protected,static,mixin".split(","),_checkReservedMemberName:function(b){-1!==this._reservedNames.indexOf(b)&&a.Error.invalidClassProperty()},_checkConstructorMember:function(b){"function"!=typeof b&&a.Error.invalidClassConstructor()},_checkOverridenMember:function(b,c){typeof b!=typeof c&&a.Error.invalidClassOverride()},_checkIfOverriddenMember:function(a,b){var c=this._extend.prototype[a];void 0!==c&&this._checkOverridenMember(b,c)},_checkMemberValue:function(a,b){"constructor"===a?this._checkConstructorMember(b):this._checkIfOverriddenMember(a,b)},_checkProperty:function(a,b){ya.prototype._checkProperty.call(this,a),this._checkMemberName(a),this._checkReservedMemberName(a),this._checkMemberValue(a,b)},_checkName:function(){ya.prototype._checkName.call(this),/^[A-Z_$][a-zA-Z0-9]*$/.exec(this._name)||a.Error.invalidClassName()},_extend:Object,_readExtend:function(){var a=Da(this._initialDefinition.$extend);a&&(this._extend=a)},_checkExtend:function(){"function"!=typeof this._extend&&a.Error.invalidClassExtend()},check:function(){this._readExtend(),this._checkExtend(),ya.prototype.check.call(this)}}),ia("define/class/constructor",{"classConstructorFunction":"This is a class constructor function, use with new"}),Object.assign(Ca.prototype,{_resolvedConstructor:b}),ia("define/class/super",{invalidClassSuper:"Invalid class super",invalidClassSuperMember:"Invalid class super member"}),Object.assign(Ca.prototype,{_get$Super:function(a,b,c){var d=this._extend.prototype,e=Ja(d[b]);return c.forEach(function(b){e[b]=La(a,e,d[b])}),e},_superifiedBody:'var _super_;\nif (this.hasOwnProperty("$super")) {\n _super_ = this.$super;\n}\nthis.$super = _classDef_._get$Super(this, _methodName_, _superMembers_);\ntry{\n var _result_ = _method_.apply(this, arguments);\n} finally {\n if (undefined === _super_) {\n delete this.$super;\n } else {\n this.$super = _super_;\n }\n}\nreturn _result_;',_getSuperifiedContext:function(a,b,c){return{_method_:a,_methodName_:b,_superMembers_:c,_classDef_:this}},_createSuperified:function(a,b,c){var d=oa(a);return d.body=this._superifiedBody,ua(d,this._getSuperifiedContext(a,b,c))},_superify:function(a,b){return /\.\$super\b/.exec(a)?this._createSuperified(a,b,Ma(a)):a}}),Object.assign(Ca.prototype,{_build:function(){var a,b;return this._resolveConstructor(),a=Ga(this),b=Object.create(this._extend.prototype),a.prototype=b,b.constructor=a,this._buildPrototype(b),a},_addMethodToPrototype:function(a,b,c){a[b]=this._superify(c,b)},_addMemberToPrototype:function(a,b,c){"function"==typeof c?this._addMethodToPrototype(a,b,c):a[b]=c},_buildPrototype:function(a){$a(this._initialDefinition,function(b,c){"$"!==c.charAt(0)&&"constructor"!==c&&this._addMemberToPrototype(a,c,b)},this)},_setResolvedConstructorToInherited:function(){this._extend!==Object&&(this._resolvedConstructor=this._extend)},_resolveConstructor:function(){this._initialDefinition.hasOwnProperty("constructor")?this._resolvedConstructor=this._superify(this._initialDefinition.constructor,"constructor"):this._setResolvedConstructorToInherited()}}),a.define=Na}); \ No newline at end of file diff --git a/build/report.history.js b/build/report.history.js index 8875bc36..dd4b8e4b 100644 --- a/build/report.history.js +++ b/build/report.history.js @@ -1 +1 @@ -__history = [{"date":"Thu, 19 Feb 2015 14:02:11 GMT","total":{"sloc":13499,"maintainability":2393.0333097905273},"average":{"sloc":374,"maintainability":"66.47"}},{"date":"Thu, 19 Feb 2015 18:07:05 GMT","total":{"sloc":13446,"maintainability":2311.37305619915},"average":{"sloc":384,"maintainability":"66.04"}},{"date":"Sat, 03 Dec 2016 16:45:15 GMT","total":{"sloc":2453,"maintainability":2324.33},"average":{"sloc":84,"maintainability":"80.15"}},{"date":"Sun, 05 Feb 2017 17:36:57 GMT","total":{"sloc":3463,"maintainability":3322.0919999999996},"average":{"sloc":84,"maintainability":"81.03"}}] \ No newline at end of file +__history = [{"date":"Thu, 19 Feb 2015 14:02:11 GMT","total":{"sloc":13499,"maintainability":2393.0333097905273},"average":{"sloc":374,"maintainability":"66.47"}},{"date":"Thu, 19 Feb 2015 18:07:05 GMT","total":{"sloc":13446,"maintainability":2311.37305619915},"average":{"sloc":384,"maintainability":"66.04"}},{"date":"Sat, 03 Dec 2016 16:45:15 GMT","total":{"sloc":2453,"maintainability":2324.33},"average":{"sloc":84,"maintainability":"80.15"}},{"date":"Sun, 05 Feb 2017 17:36:57 GMT","total":{"sloc":3463,"maintainability":3322.0919999999996},"average":{"sloc":84,"maintainability":"81.03"}},{"date":"Thu, 02 Mar 2017 17:19:26 GMT","total":{"sloc":3782,"maintainability":3372.4250000000015},"average":{"sloc":92,"maintainability":"82.25"}}] \ No newline at end of file diff --git a/build/report.history.json b/build/report.history.json index 6fec0e86..44164b8f 100644 --- a/build/report.history.json +++ b/build/report.history.json @@ -1 +1 @@ -[{"date":"Thu, 19 Feb 2015 14:02:11 GMT","total":{"sloc":13499,"maintainability":2393.0333097905273},"average":{"sloc":374,"maintainability":"66.47"}},{"date":"Thu, 19 Feb 2015 18:07:05 GMT","total":{"sloc":13446,"maintainability":2311.37305619915},"average":{"sloc":384,"maintainability":"66.04"}},{"date":"Sat, 03 Dec 2016 16:45:15 GMT","total":{"sloc":2453,"maintainability":2324.33},"average":{"sloc":84,"maintainability":"80.15"}},{"date":"Sun, 05 Feb 2017 17:36:57 GMT","total":{"sloc":3463,"maintainability":3322.0919999999996},"average":{"sloc":84,"maintainability":"81.03"}}] \ No newline at end of file +[{"date":"Thu, 19 Feb 2015 14:02:11 GMT","total":{"sloc":13499,"maintainability":2393.0333097905273},"average":{"sloc":374,"maintainability":"66.47"}},{"date":"Thu, 19 Feb 2015 18:07:05 GMT","total":{"sloc":13446,"maintainability":2311.37305619915},"average":{"sloc":384,"maintainability":"66.04"}},{"date":"Sat, 03 Dec 2016 16:45:15 GMT","total":{"sloc":2453,"maintainability":2324.33},"average":{"sloc":84,"maintainability":"80.15"}},{"date":"Sun, 05 Feb 2017 17:36:57 GMT","total":{"sloc":3463,"maintainability":3322.0919999999996},"average":{"sloc":84,"maintainability":"81.03"}},{"date":"Thu, 02 Mar 2017 17:19:26 GMT","total":{"sloc":3782,"maintainability":3372.4250000000015},"average":{"sloc":92,"maintainability":"82.25"}}] \ No newline at end of file diff --git a/build/tests.js b/build/tests.js index 60919f8a..eca3b3c2 100644 --- a/build/tests.js +++ b/build/tests.js @@ -1,2 +1,2 @@ -"use strict";describe("arraylike",function(){describe("gpf.isArrayLike",function(){it("checks if an object looks like an array",function(){assert(!0===gpf.isArrayLike([]))})})}),describe("foreach",function(){var a="Hello World!",b=[0,1,2,3,4,5,6,7,8,9],c={"number":1,"string":a,"null":null,"object":{member:"value"},"function":function(){return a}},d="number,string,null,object,function";describe("gpf.forEach",function(){it("enumerates array content",function(){var a=0,c=0;gpf.forEach(b,function(d,e,f){assert("number"==typeof e),assert(f===b),++a,c+=d}),assert(b.length===a),assert(45===c)}),it("transmits scope on array content",function(){var a,d=0,e=0;a=gpf.forEach(b,function(a,f,g){assert(this===c),assert("number"==typeof f),assert(g===b),++d,e+=a},c),assert(void 0===a),assert(b.length===d),assert(45===e)}),it("enumerates object content and handles null value",function(){var a=[],b=!0;gpf.forEach(c,function(d,e,f){assert("string"==typeof e),assert(f===c),a.push(e),"null"===e&&null!==d&&(b=!1)}),a=a.join(","),assert(d===a),assert(!0===b)}),it("transmits scope on object content",function(){var a=gpf.forEach(c,function(){assert(this===c)},c);assert(void 0===a)})})}),describe("assert",function(){describe("gpf.assert",function(){it("does not accept no message",function(){var a;try{console.expects&&console.expects("warn",/.*/),gpf.assert(!0)}catch(e_){a=e_}assert(void 0!==a)}),[!0,42,"Hello World!",{}].forEach(function(a){it("does nothing on a truthy condition - "+typeof a+" ("+a.toString()+")",function(){gpf.assert(a,"It works")})}),[!1,0,"",void 0,null].forEach(function(a){var b;b=void 0===b?"undefined":null===b?"null":a.toString(),it("throws an exception on a falsy condition - "+typeof a+" ("+b+")",function(){var b;try{console.expects&&console.expects("warn",/.*/),gpf.assert(a,"It fails")}catch(e_){b=e_}assert(void 0!==b)})})}),describe("gpf.asserts",function(){it("works with a message / boolean dictionary",function(){gpf.asserts({"It works":!0,"It also works":!0})}),it("fails on first falsy",function(){var a;try{gpf.asserts({"It works":!0,"It fails":!1})}catch(e_){a=e_}assert(void 0!==a)})})}),describe("constants",function(){describe("gpf",function(){it("does not expose any 'private' member",function(){function a(b,c){var d,e;for(d in b)b.hasOwnProperty(d)&&(assert("_"!==d.charAt(0)),e=b[d],"object"==typeof e&&-1===c.indexOf(e)&&(c.push(e),a(e,c)))}a(gpf,[gpf,gpf.internals])}),it("should expose a version",function(){assert("function"==typeof gpf.version),assert("string"==typeof gpf.version());var a=gpf.version();assert(-1!==a.indexOf(".")),assert(null!==a.match(/[0-9]+\.[0-9]+d?/))}),it("should expose the host type",function(){assert("function"==typeof gpf.host),assert("string"==typeof gpf.host());var a=gpf.host();assert(-1!==[gpf.hosts.browser,gpf.hosts.nodejs,gpf.hosts.phantomjs,gpf.hosts.rhino,gpf.hosts.unknown,gpf.hosts.wscript].indexOf(a))}),describe("gpf.hosts enumeration",function(){["browser","nodejs","phantomjs","unknown","wscript"].forEach(function(a){it("declares gpf.hosts."+a,function(){assert(void 0!==gpf.hosts[a])})})})}),gpf.internals&&describe("(internal) _gpfIsUnsignedByte",function(){var a=gpf.internals._gpfIsUnsignedByte;gpf.forEach({0:!0,"-25":!1,128:!0,256:!1,255:!0},function(b,c){var d=parseInt(c,10);b?it("accepts "+c,function(){assert(!0===a(d))}):it("rejects "+c,function(){assert(!1===a(d))})})})}),describe("string/capitalize",function(){gpf.internals&&describe("(internal) _gpfStringCapitalize",function(){var a=gpf.internals._gpfStringCapitalize;it("does nothing on empty string",function(){assert(""===a(""))}),it("uppercases the first letter",function(){assert("Word"===a("word")),assert("Two words"===a("two words")),assert("Two words"===a("Two words"))}),it("also handles accents",function(){assert("\xc9ric"===a("\xe9ric"))})})}),describe("string/replaceex",function(){gpf.internals&&describe("(internal) _gpfStringReplaceEx",function(){var a=gpf.internals._gpfStringReplaceEx;it("replaces strings recursively",function(){assert("add"===a("abc",{"a":"abc","b":"dc","c":""}))})})}),describe("string/escapefor",function(){gpf.internals&&describe("(internal) _gpfStringEscapeFor",function(){var a=gpf.internals._gpfStringEscapeFor;it("escapes for JavaScript",function(){assert('"abc\\r\\ndef"'===a("abc\r\ndef","javascript"))}),it("escapes for xml",function(){assert("<a&b>"===a("","xml"))}),it("escapes for html",function(){assert("<a&b:éèêáà>"===a("","html"))})})}),describe("compatibility",function(){function a(a){var b=new Array(5);b[2]=void 0,b[3]=3,a.call(b,function(a,b){assert(2===b||3===b),2===b?assert(void 0===a):assert(3===a)})}function b(a,b,c){var d="must expose the method "+b;a instanceof Function?it(d,function(){assert("function"==typeof a[b])}):it(d+" through prototype",function(){assert("function"==typeof a[b]),assert(!a.hasOwnProperty(b))}),-1!==c&&it(d+" with an expected arity of "+c,function(){assert(a[b].length===c)})}function c(a){var b,c,d,e=a.sample,f=a.testMethod,g=a.label,h=a.methodName,i=e[h];it(g,function(){f(i)}),gpf.internals&&(b=gpf.internals._gpfCompatibility[a.type],c=a.isStatic?b.statics:b.methods,c&&(d=c[h]),d&&d!==i&&it(g+" (compatible)",function(){f(d)}))}function d(a,d,e){return function(){var f,h,i=g[a];f=!0===e.isStatic?i:new i,b(f,d,e.length);for(h in e)e.hasOwnProperty(h)&&"function"==typeof e[h]&&c({type:a,sample:f,methodName:d,isStatic:e.isStatic,label:h,testMethod:e[h]})}}function e(a){var b,c=f[a];for(b in c)c.hasOwnProperty(b)&&describe(b,d(a,b,c[b]))}var f={Array:{every:{length:1,"must return true when it goes over all items":function(a){var b,c=[1,2,3,-6,10],d=0;b=a.call(c,function(a){return d+=a,!0}),assert(!0===b),assert(10===d)},"must return false when it stops on a given item":function(a){var b,c=[1,2,3,-6,10],d=0;b=a.call(c,function(a){return a>0&&(d+=a,!0)}),assert(!1===b),assert(6===d)},"must iterate with a bound context":function(a){var b,c=[1,2,3,-6,10],d={sum:0,index:0};b=a.call(c,function(a,b){var c=this;return assert(c===d),c.index=b,a>0&&(c.sum+=a,!0)},d),assert(!1===b),assert(6===d.sum),assert(3===d.index)},"must ignore undefined members":a},filter:{length:1,"must filter":function(a){var b,c=[1,2,3,4,5];b=a.call(c,function(a){return a%2===0}),assert(2===b.length),assert(2===b[0]),assert(4===b[1])},"must filter with a bound context":function(a){var b,c=[1,2,3,4,5],d={};b=a.call(c,function(a){return assert(this===d),a%2===0},d),assert(2===b.length),assert(2===b[0]),assert(4===b[1])},"must ignore undefined members":a},forEach:{length:1,"must iterate":function(a){var b=[1,2,3],c=0;assert("function"==typeof b.forEach),assert(!b.hasOwnProperty("forEach")),a.call(b,function(a){c+=a}),assert(6===c)},"must iterate with a bound context":function(a){var b=[1,2,3],c={sum:0};a.call(b,function(a){this.sum+=a},c),assert(6===c.sum)},"must ignore undefined members":a},indexOf:{length:1,"must expose indexOf()":function(a){var b={},c=[1,2,3,b,"abc"];assert(-1===a.call(c,4)),assert(0===a.call(c,1)),assert(3===a.call(c,b)),assert(-1===a.call(c,{})),assert(4===a.call(c,"abc"))}},map:{length:1,"must map with a bound context":function(a){var b,c={},d=[1,2,3,c,"abc"];assert("function"==typeof d.map),assert(!d.hasOwnProperty("map")),b=a.call(d,function(a,b){return assert(this===c),assert(a===d[b]),b},c),assert(b.length===d.length),assert(0===b[0]),assert(4===b[4])},"must ignore undefined members":a},reduce:{length:1,"must reduce with no initial value":function(a){function b(a,b,e,f){return assert(c===f),assert(d===e),++d,a+b}var c=[0,1,2,3,4],d=1;assert(10===a.call(c,b))},"must reduce with intial value":function(a){function b(a,b,e,f){return assert(c===f),assert(d===e),++d,a+b}var c=[0,1,2,3,4],d=0;assert(20===a.call(c,b,10))}},some:{length:1,"returns false when all members return false":function(a){var b=[2,5,8,1,4];assert(!1===a.call(b,function(a){return a>10}))},"returns true when at least one member returns true":function(a){var b=[12,5,8,1,4];assert(!0===a.call(b,function(a){return a>10}))}},from:{isStatic:!0,length:1,"works on arguments":function(a){function b(){return a.call(Array,arguments)}var c=b(1,2,3);assert(c instanceof Array),assert(3===c.length),assert(1===c[0]),assert(2===c[1]),assert(3===c[2])},"works on strings":function(a){var b=a.call(Array,"foo");assert(b instanceof Array),assert(3===b.length),assert("f"===b[0]),assert("o"===b[1]),assert("o"===b[2])},"supports callback mapping":function(a){var b=a.call(Array,[1,2,3],function(a){return a+a});assert(b instanceof Array),assert(3===b.length),assert(2===b[0]),assert(4===b[1]),assert(6===b[2])},"generates a sequence of numbers":function(a){var b=a.call(Array,{length:3},function(a,b){return b});assert(b instanceof Array),assert(3===b.length),assert(0===b[0]),assert(1===b[1]),assert(2===b[2])}},isArray:{isStatic:!0,length:1,"detects an array":function(a){assert(!0===a.call(Array,[]))},"rejects other objects":function(a){assert(!1===a.call(Array,{length:0}))}}},Function:{bind:{length:1,"must bind to a context":function(a){function b(a){assert(this===d),this.member=a}var c,d={member:null};c=a.call(b,d),c(!0),assert(!0===d.member),c.call({},!1),assert(!1===d.member)},"must return the same result":function(a){function b(a){return a}var c=a.call(b,{});assert(!1===c(!1)),assert(!0===c(!0))},"must preserve function signature":function(a){function b(a,b,c){return a+b+c}assert(3===b.length);var c=a.call(b,{});assert(3===c.length)},"must allow additional parameters binding":function(a){function b(a,b,c){return a+b+c}assert(3===b.length);var c=a.call(b,{},1);assert(2===c.length),assert(6===c(2,3))}}},Object:{create:{isStatic:!0,length:-1,"allows creating objects with a given prototype":function(a){var b=a.call(Object,{method:function(){return"myMethod"}});assert(!b.hasOwnProperty("method")),assert("function"==typeof b.method),assert("myMethod"===b.method())},"is compatible with instanceof":function(a){function b(){}b.prototype={a:function(){return"a"}};var c=a.call(Object,b.prototype);assert("a"===c.a()),assert(c instanceof b)},"allows inheritance and use of instanceof":function(a){function b(){}function c(){}b.prototype={a:function(){return"a"}},c.prototype=new b;var d=a.call(Object,c.prototype);assert("a"===d.a()),assert(d instanceof b),assert(d instanceof c)}},getPrototypeOf:{isStatic:!0,length:1,"returns prototype passed to Object.create":function(a){var b,c;b={a:function(){return"a"}},c=Object.create(b),assert(a.call(Object,c)===b)},"returns prototype from constructor":function(a){function b(){}b.prototype={constructor:b,a:function(){return"a"}};var c=new b;assert(a.call(Object,c)===b.prototype)}},keys:{isStatic:!0,length:1,"returns list of indexes of an array":function(a){var b=["a","b","c"],c=a.call(Object,b);assert(3===c.length),assert("0"===c[0]),assert("1"===c[1]),assert("2"===c[2])},"returns list of indexes of an array-like object":function(a){var b={0:"a",1:"b",2:"c"},c=a.call(Object,b);assert(3===c.length),assert(-1b)throw new Error("Triggered too soon ("+e+" does not respect the timeout delay of "+d+")")}function h(a,b,c){void 0===q&&console.error("Unexpected callback triggered when callbackDone is undefined"),e(a),f(),g(b,c),s.push(a)}function i(a){try{h(a,n,c),o=!1,p=!0,q()}catch(e_){q(e_)}}function j(b){s.push(b),a.clearTimeout(b)}function k(a){-1===s.indexOf(a)&&-1===r.indexOf(a)&&j(a)}function l(){m&&j(m),p=!1,n=new Date;var b=a.setTimeout(function(){i(b),m=void 0},c);m=b,o=!0}var m,n,o,p,q,r=[],s=[];beforeEach(function(){l()}),it("allocates a timeout id",function(){assert(void 0!==m)}),afterEach(function(){k(m)}),describe("clearing",function(){beforeEach(function(){s.push(m),a.clearTimeout(m)}),it("removes the callback from the queue",function(){a.handleTimeout()}),describe("again",function(){beforeEach(function(){a.clearTimeout(m)}),it("does not fail",function(){a.handleTimeout()})})}),describe("triggering",function(){beforeEach(function(b){r.push(m),q=b,a.handleTimeout()}),it("executes the callback from the queue",function(){assert(!0===p)}),it("removes the callback from the queue",function(){a.handleTimeout()})}),describe("sequencing with a second timeout",function(){function b(a){try{h(a,g,d),q()}catch(e_){q(e_)}}function e(a,b){r.push(f),r.push(m);var c=0;q=function(d){d?a(d):b===++c&&a()}}var f,g;beforeEach(function(){g=new Date,l();var c=a.setTimeout(function(){b(c)},d);f=c}),it("allocates a different timeout id",function(){assert(void 0!==f),assert(f!==m)}),afterEach(function(){k(f)}),describe("clearing the second timeout",function(){beforeEach(function(){s.push(f),a.clearTimeout(f)}),describe("triggering",function(){beforeEach(function(b){r.push(m),q=b,a.handleTimeout()}),it("executes the remaining callback from the queue",function(){assert(!0===p)}),it("removes all callbacks from the queue",function(){a.handleTimeout()})})}),describe("creating and cleaning a third timeout",function(){it("prevents execution",function(b){e(b,3);var d=a.setTimeout(function(){q(new Error("The third timeout was triggered"))},10*c);a.clearTimeout(d),a.handleTimeout(),q()})}),describe("triggering",function(){beforeEach(function(b){e(b,2),a.handleTimeout()}),it("executes the callbacks from the queue",function(){assert(!0===p)}),it("removed all callbacks from the queue",function(){a.handleTimeout()})})})}}describe("exposed API",a({checkDelay:!0,setTimeout:function(a,b){return setTimeout(a,b)},clearTimeout:function(a){clearTimeout(a)},handleTimeout:function(){}})),gpf.internals&&setTimeout!==gpf.internals._gpSetTimeoutPolyfill&&describe("(internal)",a({checkDelay:!1,setTimeout:gpf.internals._gpSetTimeoutPolyfill,clearTimeout:gpf.internals._gpfClearTimeoutPolyfill,handleTimeout:gpf.internals._gpfHandleTimeout}))}),describe("compatibility/json",function(){function a(b,c){var d=typeof b;return d===typeof c&&("object"===d&&b&&c?Object.keys(b).every(function(d){return c.hasOwnProperty(d)&&a(b[d],c[d])}):b===c)}var b=[{label:"empty object",obj:{},json:"{}"},{label:"simple string property",obj:{a:"123"},json:'{"a":"123"}'},{label:"simple number property",obj:{a:123},json:'{"a":123}'},{label:"simple boolean properties",obj:{a:!0,b:!1},json:'{"a":true,"b":false}'},{label:"mixed simple properties",obj:{a:"123",b:123,c:!0,d:{}},json:'{"a":"123","b":123,"c":true,"d":{}}'},{label:"function",obj:{a:123,b:function(){}},json:'{"a":123}',parse:!1},{label:"array",obj:{a:[1,2,3]},json:'{"a":[1,2,3]}'},{label:"null",obj:{a:null},json:'{"a":null}'}];describe("JSON object",function(){it("exists",function(){assert("undefined"!=typeof JSON)})}),describe("JSON.stringify",function(){b.forEach(function(a){it("works on "+a.label,function(){assert(JSON.stringify(a.obj)===a.json)})})}),describe("JSON.parse",function(){b.forEach(function(b){!1!==b.parse&&it("works on "+b.label,function(){var c=JSON.parse(b.json);assert(!0===a(c,b.obj))})})}),gpf.internals&&describe("(internal)",function(){describe("_gpfJsonStringifyPolyfill",function(){b.forEach(function(a){it("works on "+a.label,function(){assert(gpf.internals._gpfJsonStringifyPolyfill(a.obj)===a.json)})})}),describe("_gpfJsonParsePolyfill",function(){b.forEach(function(b){!1!==b.parse&&it("works on "+b.label,function(){var c=gpf.internals._gpfJsonParsePolyfill(b.json);assert(!0===a(c,b.obj))})})})})}),describe("context",function(){describe("gpf.context",function(){it("resolves the global context",function(){if(assert("function"==typeof gpf.context),assert(null!==gpf.context()),gpf.hosts.browser===gpf.host())assert(window===gpf.context());else if(gpf.hosts.nodejs===gpf.host()||gpf.hosts.phantomjs===gpf.host())assert(global===gpf.context());else{var a=function(){return this}();assert(a===gpf.context())}}),it("resolves gpf",function(){assert(gpf===gpf.context("gpf"))}),it("resolves any symbol",function(){assert(gpf.context===gpf.context("gpf.context"))}),it("returns undefined if not existing",function(){assert(void 0===gpf.context("gpf.not-existing"))}),it("returns undefined if not existing (deep dive)",function(){assert(void 0===gpf.context("gpf.not-existing.really-not"))})}),gpf.internals&&describe("_gpfContext",function(){var a=gpf.internals._gpfContext;it("can build a context",function(){var b=gpf.context(),c={};b.testContextJS=c;var d=a(["testContextJS","folder","name"],!0);assert(b.testContextJS===c),assert(b.testContextJS.folder.name===d),delete b.testContextJS})})}),describe("extend",function(){describe("gpf.extend",function(){it("extends objects members",function(){var a={"member1":"member1","member2":2},b={"newMember":!0},c=gpf.extend(a,b);assert(c===a),assert("member1"===c.member1),assert(2===c.member2),assert(c.newMember===!0),assert(b.newMember===!0)}),it("overwrites existing members",function(){var a={"member1":"member1"},b={"member1":!1},c=gpf.extend(a,b);assert(c.member1===!1)}),it("supports more than one source parameter",function(){var a={"member1":"member1","member2":2},b=gpf.extend(a,{"source1":1,"member1":"member1.1"},{"source2":2,"member1":"member1.2"});assert("member1.2"===b.member1),assert(2===b.member2),assert(1===b.source1),assert(2===b.source2)})})}),describe("error",function(){describe("gpf.Error",function(){it("is used as an exception",function(){var a;try{gpf.Error.abstractMethod()}catch(e_){a=e_}assert(a instanceof Error),assert(a instanceof gpf.Error),assert(a instanceof gpf.Error.AbstractMethod),assert(a.constructor===gpf.Error.AbstractMethod)}),it("is documented",function(){var a;try{gpf.Error.abstractMethod()}catch(e_){a=e_}assert(a.code===gpf.Error.CODE_ABSTRACTMETHOD),assert(a.code===gpf.Error.abstractMethod.CODE),assert("abstractMethod"===a.name),assert("Abstract method"===a.message)}),it("can use substitution for message",function(){var a;try{gpf.Error.assertionFailed({message:"Test"})}catch(e_){a=e_}assert(a instanceof gpf.Error.AssertionFailed),assert(a.code===gpf.Error.CODE_ASSERTIONFAILED),assert(a.code===gpf.Error.assertionFailed.CODE),assert("assertionFailed"===a.name),assert("Assertion failed: Test"===a.message)})})}),describe("function",function(){if(gpf.internals){var a=gpf.internals._gpfFunctionDescribe;describe("_gpfFunctionDescribe",function(){it("describes a named function",function(){var b=a(function(a,b){return a+b});assert("test"===b.name),assert(2===b.parameters.length),assert("a"===b.parameters[0]),assert("b"===b.parameters[1]),assert(b.body.indexOf("return a + b;")!==-1)}),it("identifies an unnamed function",function(){var b=a(function(){return 0});assert(!b.name),assert(!b.parameters),assert(b.body.indexOf("return 0;")!==-1)}),it("identifies empty function",function(){var b=a(function(){});assert(void 0===b.body)}),it("filters out comments",function(){function b(a,b,c){return a+b+c}var c=a(b);assert("test2"===c.name),assert(3===c.parameters.length),assert("a"===c.parameters[0]),assert("b"===c.parameters[1]),assert("c"===c.parameters[2]),assert(c.body.indexOf("comments are removed")===-1)})}),describe("_gpfFunctionBuild",function(){var a=gpf.internals._gpfFunctionBuild;it("builds an empty anonymous function",function(){var b=a({});assert("function"==typeof b),assert(""===b.compatibleName())}),it("builds a named function",function(){var b=a({name:"test"});assert("test"===b.compatibleName())}),it("builds a function with named parameters",function(){var b=a({parameters:["a","b","c"],body:"return a + b + c;"});assert(3===b.length),assert(6===b(1,2,3))}),it("builds a function with external context",function(){var b=a({body:"return a;"},{a:"Hello World!"});assert(0===b.length),assert("Hello World!"===b()); -})})}}),describe("define/check",function(){gpf.internals&&describe("(internal) _GpfEntityDefinition",function(){var a=gpf.internals._GpfEntityDefinition,b=gpf.internals._gpfDefineBuildTypedEntity;it("must have an entity type",function(){var a;try{b({})}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidEntityType)}),it("checks for a valid name",function(){var a;try{b({$type:"class"})}catch(e_){a=e_}assert(a instanceof gpf.Error.MissingEntityName)}),it("validates minimal requirement (type and name)",function(){b({$type:"class",$name:"Test"})}),it("rejects invalid properties",function(){var a;try{b({$type:"class",$name:"Test",$fail:!0})}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidEntity$Property)}),it("converts $class into _type and _name",function(){var c=b({$class:"Test"});assert(c instanceof a),assert("class"===c._type),assert("Test"===c._name)}),it("converts $class into _type, _name and _namespace (absolute)",function(){var a=b({$class:"gpf.test.Test"});assert("class"===a._type),assert("Test"===a._name),assert("gpf.test"===a._namespace)}),it("converts $class into _type, _name and _namespace (relative)",function(){var a=b({$class:"test.Test",$namespace:"gpf"});assert("class"===a._type),assert("Test"===a._name),assert("gpf.test"===a._namespace)}),it("prioritize $class over $name",function(){var a=b({$class:"Test",$name:"Any"});assert("class"===a._type),assert("Test"===a._name)}),it("validates namespace",function(){b({$class:"Test",$namespace:"lowerCamelCase.$accepted._also.numbers456"}),b({$class:"Test",$namespace:"simple"}),b({$class:"Test",$namespace:""})}),["endingPointIsNotOK.","startingNumberIsNotOK.4test","$isOKOnlyAtBeginning.test$","_isOKOnlyAtBeginning.test_","CapitalFirstLetterIsNotOK"].forEach(function(a){it("rejects invalid namespace ("+a+")",function(){var c;try{b({$class:"Test",$namespace:a})}catch(e_){c=e_}assert(c instanceof gpf.Error.InvalidEntityNamespace)})})})}),describe("define/class/check",function(){gpf.internals&&describe("(internal) _GpfClassDefinition",function(){var a=gpf.internals._GpfClassDefinition,b=gpf.internals._gpfDefineBuildTypedEntity;it("is used for class definition",function(){var c=b({$class:"Test"});assert(c instanceof a)}),it("accepts a valid class definition",function(){b({$class:"Test",member:function(){}})}),["startingWithLowercaseLetterIsNotOK","The$signIsForbbidenIfNotAtTheBeginning","The_signIsForbbidenIfNotAtTheBeginning"].forEach(function(a){it("rejects invalid class name ("+a+")",function(){var c;try{b({$class:a})}catch(e_){c=e_}assert(c instanceof gpf.Error.InvalidClassName)})}),["StartingWithUppercaseLetterIsNotOK","the$signIsForbbidenIfNotAtTheBeginning","the_signIsForbbidenIfNotAtTheBeginning","class"].forEach(function(a){it("rejects invalid property name ("+a+")",function(){var c,d={$class:"Test"};d[a]=!0;try{b(d)}catch(e_){c=e_}assert(c instanceof gpf.Error.InvalidClassProperty)})}),it("rejects invalid $extend",function(){var a;try{b({$class:"Test",$extend:12})}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidClassExtend)}),it("accepts native $extend",function(){b({$class:"Test",$extend:String})}),it("accepts contextual $extend",function(){b({$class:"Test",$extend:"String"})})})}),describe("define",function(){var a={};before(function(){gpf.context().test=a}),after(function(){delete gpf.context().test}),describe("gpf.define",function(){it("accepts only one parameter",function(){assert("function"==typeof gpf.define),assert(1===gpf.define.length)}),describe("Simple class description",function(){describe("Validation",function(){it("checks that he entity type is specified",function(){var a;try{gpf.define({})}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidEntityType)}),["1NumberAtTheBeginningIsNotOK","noUppercaseFirstLetterIsNotOK","DollarSignAnywhereIsNotOK$"].forEach(function(a){it("rejects invalid class name ("+a+")",function(){var b;try{gpf.define({$class:a})}catch(e_){b=e_}assert(b instanceof gpf.Error.InvalidClassName)})}),["A","$B","_C","Test123"].forEach(function(a){it("validates class name ("+a+")",function(){var b;try{gpf.define({$class:a})}catch(e_){b=e_}assert(void 0===b)})}),it("rejects invalid $ property names",function(){var a;try{gpf.define({$class:"Test",$test:!1})}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidEntity$Property)}),it("rejects invalid property names (reserved keywords)",function(){var a;try{gpf.define({$class:"Test","super":!1})}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidClassProperty)})})}),describe("Definition",function(){var b,c;before(function(){b=gpf.define({$class:"A",_member:"defaultValue",getMember:function(){return this._member},"constructor":function(a){a&&(this._member=a),this._constructorOfA=!0}}),c=new b}),it("prevents constructor functions to be used without new",function(){var a;try{b()}catch(e_){a=e_}assert(a instanceof gpf.Error.ClassConstructorFunction)}),it("handles instanceof",function(){assert(c instanceof b)}),it("calls constructor function",function(){assert(c._constructorOfA)}),it("exposes methods",function(){assert("function"==typeof c.getMember),assert("defaultValue"===c.getMember())}),describe("Subclassing",function(){var c,d;before(function(){c=gpf.define({$class:"test.B",$extend:b,"constructor":function(a){this.$super("valueOfB"),this._constructorOfB=a},getMember:function(){return this.$super()+"-inB"},setMember:function(a){this._member=a}}),d=new c(3475)}),it("handles instanceof",function(){assert(d instanceof b),assert(d instanceof c)}),it("handles namespace",function(){assert(a.B===c)}),it("calls the constructor function",function(){assert(3475===d._constructorOfB)}),it("calls the proper $super()",function(){assert(d._constructorOfA),assert("valueOfB-inB"===d.getMember())})})})})}); \ No newline at end of file +"use strict";describe("arraylike",function(){describe("gpf.isArrayLike",function(){it("checks if an object looks like an array",function(){assert(!0===gpf.isArrayLike([]))})})}),describe("foreach",function(){var a="Hello World!",b=[0,1,2,3,4,5,6,7,8,9],c={"number":1,"string":a,"null":null,"object":{member:"value"},"function":function(){return a}},d="number,string,null,object,function";describe("gpf.forEach",function(){it("enumerates array content",function(){var a=0,c=0;gpf.forEach(b,function(d,e,f){assert("number"==typeof e),assert(f===b),++a,c+=d}),assert(b.length===a),assert(45===c)}),it("transmits scope on array content",function(){var a,d=0,e=0;a=gpf.forEach(b,function(a,f,g){assert(this===c),assert("number"==typeof f),assert(g===b),++d,e+=a},c),assert(void 0===a),assert(b.length===d),assert(45===e)}),it("enumerates object content and handles null value",function(){var a=[],b=!0;gpf.forEach(c,function(d,e,f){assert("string"==typeof e),assert(f===c),a.push(e),"null"===e&&null!==d&&(b=!1)}),a=a.join(","),assert(d===a),assert(!0===b)}),it("transmits scope on object content",function(){var a=gpf.forEach(c,function(){assert(this===c)},c);assert(void 0===a)})})}),describe("assert",function(){describe("gpf.assert",function(){it("does not accept no message",function(){var a;try{console.expects&&console.expects("warn",/.*/),gpf.assert(!0)}catch(e_){a=e_}assert(void 0!==a)}),[!0,42,"Hello World!",{}].forEach(function(a){it("does nothing on a truthy condition - "+typeof a+" ("+a.toString()+")",function(){gpf.assert(a,"It works")})}),[!1,0,"",void 0,null].forEach(function(a){var b;b=void 0===b?"undefined":null===b?"null":a.toString(),it("throws an exception on a falsy condition - "+typeof a+" ("+b+")",function(){var b;try{console.expects&&console.expects("warn",/.*/),gpf.assert(a,"It fails")}catch(e_){b=e_}assert(void 0!==b)})})}),describe("gpf.asserts",function(){it("works with a message / boolean dictionary",function(){gpf.asserts({"It works":!0,"It also works":!0})}),it("fails on first falsy",function(){var a;try{gpf.asserts({"It works":!0,"It fails":!1})}catch(e_){a=e_}assert(void 0!==a)})})}),describe("constants",function(){describe("gpf",function(){it("does not expose any 'private' member",function(){function a(b,c){var d,e;for(d in b)b.hasOwnProperty(d)&&(assert("_"!==d.charAt(0)),e=b[d],"object"==typeof e&&-1===c.indexOf(e)&&(c.push(e),a(e,c)))}a(gpf,[gpf,gpf.internals])}),it("should expose a version",function(){assert("function"==typeof gpf.version),assert("string"==typeof gpf.version());var a=gpf.version();assert(-1!==a.indexOf(".")),assert(null!==a.match(/[0-9]+\.[0-9]+d?/))}),it("should expose the host type",function(){assert("function"==typeof gpf.host),assert("string"==typeof gpf.host());var a=gpf.host();assert(-1!==[gpf.hosts.browser,gpf.hosts.nodejs,gpf.hosts.phantomjs,gpf.hosts.rhino,gpf.hosts.unknown,gpf.hosts.wscript].indexOf(a))}),describe("gpf.hosts enumeration",function(){["browser","nodejs","phantomjs","unknown","wscript"].forEach(function(a){it("declares gpf.hosts."+a,function(){assert(void 0!==gpf.hosts[a])})})})}),gpf.internals&&describe("(internal) _gpfIsUnsignedByte",function(){var a=gpf.internals._gpfIsUnsignedByte;gpf.forEach({0:!0,"-25":!1,128:!0,256:!1,255:!0},function(b,c){var d=parseInt(c,10);b?it("accepts "+c,function(){assert(!0===a(d))}):it("rejects "+c,function(){assert(!1===a(d))})})})}),describe("string/capitalize",function(){gpf.internals&&describe("(internal) _gpfStringCapitalize",function(){var a=gpf.internals._gpfStringCapitalize;it("does nothing on empty string",function(){assert(""===a(""))}),it("uppercases the first letter",function(){assert("Word"===a("word")),assert("Two words"===a("two words")),assert("Two words"===a("Two words"))}),it("also handles accents",function(){assert("\xc9ric"===a("\xe9ric"))})})}),describe("string/replaceex",function(){gpf.internals&&describe("(internal) _gpfStringReplaceEx",function(){var a=gpf.internals._gpfStringReplaceEx;it("replaces strings recursively",function(){assert("add"===a("abc",{"a":"abc","b":"dc","c":""}))})})}),describe("string/escapefor",function(){gpf.internals&&describe("(internal) _gpfStringEscapeFor",function(){var a=gpf.internals._gpfStringEscapeFor;it("escapes for JavaScript",function(){assert('"abc\\r\\ndef"'===a("abc\r\ndef","javascript"))}),it("escapes for xml",function(){assert("<a&b>"===a("","xml"))}),it("escapes for html",function(){assert("<a&b:éèêáà>"===a("","html"))})})}),describe("compatibility",function(){function a(a){var b=new Array(5);b[2]=void 0,b[3]=3,a.call(b,function(a,b){assert(2===b||3===b),2===b?assert(void 0===a):assert(3===a)})}function b(a,b,c){var d="must expose the method "+b;a instanceof Function?it(d,function(){assert("function"==typeof a[b])}):it(d+" through prototype",function(){assert("function"==typeof a[b]),assert(!a.hasOwnProperty(b))}),-1!==c&&it(d+" with an expected arity of "+c,function(){assert(a[b].length===c)})}function c(a){var b,c,d,e=a.sample,f=a.testMethod,g=a.label,h=a.methodName,i=e[h];it(g,function(){f(i)}),gpf.internals&&(b=gpf.internals._gpfCompatibility[a.type],c=a.isStatic?b.statics:b.methods,c&&(d=c[h]),d&&d!==i&&it(g+" (compatible)",function(){f(d)}))}function d(a,d,e){return function(){var f,h,i=g[a];f=!0===e.isStatic?i:new i,b(f,d,e.length);for(h in e)e.hasOwnProperty(h)&&"function"==typeof e[h]&&c({type:a,sample:f,methodName:d,isStatic:e.isStatic,label:h,testMethod:e[h]})}}function e(a){var b,c=f[a];for(b in c)c.hasOwnProperty(b)&&describe(b,d(a,b,c[b]))}var f={Array:{every:{length:1,"must return true when it goes over all items":function(a){var b,c=[1,2,3,-6,10],d=0;b=a.call(c,function(a){return d+=a,!0}),assert(!0===b),assert(10===d)},"must return false when it stops on a given item":function(a){var b,c=[1,2,3,-6,10],d=0;b=a.call(c,function(a){return a>0&&(d+=a,!0)}),assert(!1===b),assert(6===d)},"must iterate with a bound context":function(a){var b,c=[1,2,3,-6,10],d={sum:0,index:0};b=a.call(c,function(a,b){var c=this;return assert(c===d),c.index=b,a>0&&(c.sum+=a,!0)},d),assert(!1===b),assert(6===d.sum),assert(3===d.index)},"must ignore undefined members":a},filter:{length:1,"must filter":function(a){var b,c=[1,2,3,4,5];b=a.call(c,function(a){return a%2===0}),assert(2===b.length),assert(2===b[0]),assert(4===b[1])},"must filter with a bound context":function(a){var b,c=[1,2,3,4,5],d={};b=a.call(c,function(a){return assert(this===d),a%2===0},d),assert(2===b.length),assert(2===b[0]),assert(4===b[1])},"must ignore undefined members":a},forEach:{length:1,"must iterate":function(a){var b=[1,2,3],c=0;assert("function"==typeof b.forEach),assert(!b.hasOwnProperty("forEach")),a.call(b,function(a){c+=a}),assert(6===c)},"must iterate with a bound context":function(a){var b=[1,2,3],c={sum:0};a.call(b,function(a){this.sum+=a},c),assert(6===c.sum)},"must ignore undefined members":a},indexOf:{length:1,"must expose indexOf()":function(a){var b={},c=[1,2,3,b,"abc"];assert(-1===a.call(c,4)),assert(0===a.call(c,1)),assert(3===a.call(c,b)),assert(-1===a.call(c,{})),assert(4===a.call(c,"abc"))}},map:{length:1,"must map with a bound context":function(a){var b,c={},d=[1,2,3,c,"abc"];assert("function"==typeof d.map),assert(!d.hasOwnProperty("map")),b=a.call(d,function(a,b){return assert(this===c),assert(a===d[b]),b},c),assert(b.length===d.length),assert(0===b[0]),assert(4===b[4])},"must ignore undefined members":a},reduce:{length:1,"must reduce with no initial value":function(a){function b(a,b,e,f){return assert(c===f),assert(d===e),++d,a+b}var c=[0,1,2,3,4],d=1;assert(10===a.call(c,b))},"must reduce with intial value":function(a){function b(a,b,e,f){return assert(c===f),assert(d===e),++d,a+b}var c=[0,1,2,3,4],d=0;assert(20===a.call(c,b,10))}},some:{length:1,"returns false when all members return false":function(a){var b=[2,5,8,1,4];assert(!1===a.call(b,function(a){return a>10}))},"returns true when at least one member returns true":function(a){var b=[12,5,8,1,4];assert(!0===a.call(b,function(a){return a>10}))}},from:{isStatic:!0,length:1,"works on arguments":function(a){function b(){return a.call(Array,arguments)}var c=b(1,2,3);assert(c instanceof Array),assert(3===c.length),assert(1===c[0]),assert(2===c[1]),assert(3===c[2])},"works on strings":function(a){var b=a.call(Array,"foo");assert(b instanceof Array),assert(3===b.length),assert("f"===b[0]),assert("o"===b[1]),assert("o"===b[2])},"supports callback mapping":function(a){var b=a.call(Array,[1,2,3],function(a){return a+a});assert(b instanceof Array),assert(3===b.length),assert(2===b[0]),assert(4===b[1]),assert(6===b[2])},"generates a sequence of numbers":function(a){var b=a.call(Array,{length:3},function(a,b){return b});assert(b instanceof Array),assert(3===b.length),assert(0===b[0]),assert(1===b[1]),assert(2===b[2])}},isArray:{isStatic:!0,length:1,"detects an array":function(a){assert(!0===a.call(Array,[]))},"rejects other objects":function(a){assert(!1===a.call(Array,{length:0}))}}},Function:{bind:{length:1,"must bind to a context":function(a){function b(a){assert(this===d),this.member=a}var c,d={member:null};c=a.call(b,d),c(!0),assert(!0===d.member),c.call({},!1),assert(!1===d.member)},"must return the same result":function(a){function b(a){return a}var c=a.call(b,{});assert(!1===c(!1)),assert(!0===c(!0))},"must preserve function signature":function(a){function b(a,b,c){return a+b+c}assert(3===b.length);var c=a.call(b,{});assert(3===c.length)},"must allow additional parameters binding":function(a){function b(a,b,c){return a+b+c}assert(3===b.length);var c=a.call(b,{},1);assert(2===c.length),assert(6===c(2,3))}}},Object:{assign:{isStatic:!0,length:2,"extends objects members":function(a){var b={"member1":"member1","member2":2},c={"newMember":!0},d=a.call(Object,b,c);assert(d===b),assert("member1"===d.member1),assert(2===d.member2),assert(d.newMember===!0),assert(c.newMember===!0)},"overwrites existing members":function(a){var b={"member1":"member1"},c={"member1":!1},d=a.call(Object,b,c);assert(d.member1===!1)},"supports more than one source parameter":function(a){var b={"member1":"member1","member2":2},c=a.call(Object,b,{"source1":1,"member1":"member1.1"},{"source2":2,"member1":"member1.2"});assert("member1.2"===c.member1),assert(2===c.member2),assert(1===c.source1),assert(2===c.source2)}},create:{isStatic:!0,length:-1,"allows creating objects with a given prototype":function(a){var b=a.call(Object,{method:function(){return"myMethod"}});assert(!b.hasOwnProperty("method")),assert("function"==typeof b.method),assert("myMethod"===b.method())},"is compatible with instanceof":function(a){function b(){}b.prototype={a:function(){return"a"}};var c=a.call(Object,b.prototype);assert("a"===c.a()),assert(c instanceof b)},"allows inheritance and use of instanceof":function(a){function b(){}function c(){}b.prototype={a:function(){return"a"}},c.prototype=new b;var d=a.call(Object,c.prototype);assert("a"===d.a()),assert(d instanceof b),assert(d instanceof c)}},getPrototypeOf:{isStatic:!0,length:1,"returns prototype passed to Object.create":function(a){var b,c;b={a:function(){return"a"}},c=Object.create(b),assert(a.call(Object,c)===b)},"returns prototype from constructor":function(a){function b(){}b.prototype={constructor:b,a:function(){return"a"}};var c=new b;assert(a.call(Object,c)===b.prototype)}},keys:{isStatic:!0,length:1,"returns list of indexes of an array":function(a){var b=["a","b","c"],c=a.call(Object,b);assert(3===c.length),assert("0"===c[0]),assert("1"===c[1]),assert("2"===c[2])},"returns list of indexes of an array-like object":function(a){var b={0:"a",1:"b",2:"c"},c=a.call(Object,b);assert(3===c.length),assert(-1b)throw new Error("Triggered too soon ("+e+" does not respect the timeout delay of "+d+")")}function h(a,b,c){void 0===q&&console.error("Unexpected callback triggered when callbackDone is undefined"),e(a),f(),g(b,c),s.push(a)}function i(a){try{h(a,n,c),o=!1,p=!0,q()}catch(e_){q(e_)}}function j(b){s.push(b),a.clearTimeout(b)}function k(a){-1===s.indexOf(a)&&-1===r.indexOf(a)&&j(a)}function l(){m&&j(m),p=!1,n=new Date;var b=a.setTimeout(function(){i(b),m=void 0},c);m=b,o=!0}var m,n,o,p,q,r=[],s=[];beforeEach(function(){l()}),it("allocates a timeout id",function(){assert(void 0!==m)}),afterEach(function(){k(m)}),describe("clearing",function(){beforeEach(function(){s.push(m),a.clearTimeout(m)}),it("removes the callback from the queue",function(){a.handleTimeout()}),describe("again",function(){beforeEach(function(){a.clearTimeout(m)}),it("does not fail",function(){a.handleTimeout()})})}),describe("triggering",function(){beforeEach(function(b){r.push(m),q=b,a.handleTimeout()}),it("executes the callback from the queue",function(){assert(!0===p)}),it("removes the callback from the queue",function(){a.handleTimeout()})}),describe("sequencing with a second timeout",function(){function b(a){try{h(a,g,d),q()}catch(e_){q(e_)}}function e(a,b){r.push(f),r.push(m);var c=0;q=function(d){d?a(d):b===++c&&a()}}var f,g;beforeEach(function(){g=new Date,l();var c=a.setTimeout(function(){b(c)},d);f=c}),it("allocates a different timeout id",function(){assert(void 0!==f),assert(f!==m)}),afterEach(function(){k(f)}),describe("clearing the second timeout",function(){beforeEach(function(){s.push(f),a.clearTimeout(f)}),describe("triggering",function(){beforeEach(function(b){r.push(m),q=b,a.handleTimeout()}),it("executes the remaining callback from the queue",function(){assert(!0===p)}),it("removes all callbacks from the queue",function(){a.handleTimeout()})})}),describe("creating and cleaning a third timeout",function(){it("prevents execution",function(b){e(b,3);var d=a.setTimeout(function(){q(new Error("The third timeout was triggered"))},10*c);a.clearTimeout(d),a.handleTimeout(),q()})}),describe("triggering",function(){beforeEach(function(b){e(b,2),a.handleTimeout()}),it("executes the callbacks from the queue",function(){assert(!0===p)}),it("removed all callbacks from the queue",function(){a.handleTimeout()})})})}}describe("exposed API",a({checkDelay:!0,setTimeout:function(a,b){return setTimeout(a,b)},clearTimeout:function(a){clearTimeout(a)},handleTimeout:function(){}})),gpf.internals&&setTimeout!==gpf.internals._gpSetTimeoutPolyfill&&describe("(internal)",a({checkDelay:!1,setTimeout:gpf.internals._gpSetTimeoutPolyfill,clearTimeout:gpf.internals._gpfClearTimeoutPolyfill,handleTimeout:gpf.internals._gpfHandleTimeout}))}),describe("compatibility/json",function(){function a(b,c){var d=typeof b;return d===typeof c&&("object"===d&&b&&c?Object.keys(b).every(function(d){return c.hasOwnProperty(d)&&a(b[d],c[d])}):b===c)}var b=[{label:"empty object",obj:{},json:"{}"},{label:"simple string property",obj:{a:"123"},json:'{"a":"123"}'},{label:"simple number property",obj:{a:123},json:'{"a":123}'},{label:"simple boolean properties",obj:{a:!0,b:!1},json:'{"a":true,"b":false}'},{label:"mixed simple properties",obj:{a:"123",b:123,c:!0,d:{}},json:'{"a":"123","b":123,"c":true,"d":{}}'},{label:"function",obj:{a:123,b:function(){}},json:'{"a":123}',parse:!1},{label:"array",obj:{a:[1,2,3]},json:'{"a":[1,2,3]}'},{label:"null",obj:{a:null},json:'{"a":null}'}];describe("JSON object",function(){it("exists",function(){assert("undefined"!=typeof JSON)})}),describe("JSON.stringify",function(){b.forEach(function(a){it("works on "+a.label,function(){assert(JSON.stringify(a.obj)===a.json)})})}),describe("JSON.parse",function(){b.forEach(function(b){!1!==b.parse&&it("works on "+b.label,function(){var c=JSON.parse(b.json);assert(!0===a(c,b.obj))})})}),gpf.internals&&describe("(internal)",function(){describe("_gpfJsonStringifyPolyfill",function(){b.forEach(function(a){it("works on "+a.label,function(){assert(gpf.internals._gpfJsonStringifyPolyfill(a.obj)===a.json)})})}),describe("_gpfJsonParsePolyfill",function(){b.forEach(function(b){!1!==b.parse&&it("works on "+b.label,function(){var c=gpf.internals._gpfJsonParsePolyfill(b.json);assert(!0===a(c,b.obj))})})})})}),describe("context",function(){describe("gpf.context",function(){it("resolves the global context",function(){if(assert("function"==typeof gpf.context),assert(null!==gpf.context()),gpf.hosts.browser===gpf.host())assert(window===gpf.context());else if(gpf.hosts.nodejs===gpf.host()||gpf.hosts.phantomjs===gpf.host())assert(global===gpf.context());else{var a=function(){return this}();assert(a===gpf.context())}}),it("resolves gpf",function(){assert(gpf===gpf.context("gpf"))}),it("resolves any symbol",function(){assert(gpf.context===gpf.context("gpf.context"))}),it("returns undefined if not existing",function(){assert(void 0===gpf.context("gpf.not-existing"))}),it("returns undefined if not existing (deep dive)",function(){assert(void 0===gpf.context("gpf.not-existing.really-not"))})}),gpf.internals&&describe("_gpfContext",function(){var a=gpf.internals._gpfContext;it("can build a context",function(){var b=gpf.context(),c={};b.testContextJS=c;var d=a(["testContextJS","folder","name"],!0);assert(b.testContextJS===c),assert(b.testContextJS.folder.name===d),delete b.testContextJS})})}),describe("extend",function(){describe("gpf.extend",function(){it("extends objects members",function(){var a={"member1":"member1","member2":2},b={"newMember":!0},c=gpf.extend(a,b);assert(c===a),assert("member1"===c.member1),assert(2===c.member2),assert(c.newMember===!0),assert(b.newMember===!0)}),it("overwrites existing members",function(){var a={"member1":"member1"},b={"member1":!1},c=gpf.extend(a,b);assert(c.member1===!1)}),it("supports more than one source parameter",function(){var a={"member1":"member1","member2":2},b=gpf.extend(a,{"source1":1,"member1":"member1.1"},{"source2":2,"member1":"member1.2"});assert("member1.2"===b.member1),assert(2===b.member2),assert(1===b.source1),assert(2===b.source2)})})}),describe("error",function(){describe("gpf.Error",function(){it("is used as an exception",function(){var a;try{gpf.Error.abstractMethod()}catch(e_){a=e_}assert(a instanceof Error),assert(a instanceof gpf.Error),assert(a instanceof gpf.Error.AbstractMethod),assert(a.constructor===gpf.Error.AbstractMethod)}),it("is documented",function(){var a;try{gpf.Error.abstractMethod()}catch(e_){a=e_}assert(a.code===gpf.Error.CODE_ABSTRACTMETHOD),assert(a.code===gpf.Error.abstractMethod.CODE),assert("abstractMethod"===a.name),assert("Abstract method"===a.message)}),it("can use substitution for message",function(){var a;try{gpf.Error.assertionFailed({message:"Test"})}catch(e_){a=e_}assert(a instanceof gpf.Error.AssertionFailed),assert(a.code===gpf.Error.CODE_ASSERTIONFAILED),assert(a.code===gpf.Error.assertionFailed.CODE),assert("assertionFailed"===a.name),assert("Assertion failed: Test"===a.message)})})}),describe("function",function(){if(gpf.internals){var a=gpf.internals._gpfFunctionDescribe;describe("_gpfFunctionDescribe",function(){it("describes a named function",function(){var b=a(function(a,b){return a+b});assert("test"===b.name),assert(2===b.parameters.length),assert("a"===b.parameters[0]),assert("b"===b.parameters[1]),assert(b.body.indexOf("return a + b;")!==-1)}),it("identifies an unnamed function",function(){var b=a(function(){return 0});assert(!b.name),assert(!b.parameters),assert(b.body.indexOf("return 0;")!==-1)}),it("identifies empty function",function(){var b=a(function(){});assert(void 0===b.body)}),it("filters out comments",function(){function b(a,b,c){return a+b+c}var c=a(b);assert("test2"===c.name),assert(3===c.parameters.length),assert("a"===c.parameters[0]),assert("b"===c.parameters[1]), +assert("c"===c.parameters[2]),assert(c.body.indexOf("comments are removed")===-1)})}),describe("_gpfFunctionBuild",function(){var a=gpf.internals._gpfFunctionBuild;it("builds an empty anonymous function",function(){var b=a({});assert("function"==typeof b),assert(""===b.compatibleName())}),it("builds a named function",function(){var b=a({name:"test"});assert("test"===b.compatibleName())}),it("builds a function with named parameters",function(){var b=a({parameters:["a","b","c"],body:"return a + b + c;"});assert(3===b.length),assert(6===b(1,2,3))}),it("builds a function with external context",function(){var b=a({body:"return a;"},{a:"Hello World!"});assert(0===b.length),assert("Hello World!"===b())})})}}),describe("define/check",function(){gpf.internals&&describe("(internal) _GpfEntityDefinition",function(){var a=gpf.internals._GpfEntityDefinition,b=gpf.internals._gpfDefineBuildTypedEntity;it("must have an entity type",function(){var a;try{b({})}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidEntityType)}),it("checks for a valid name",function(){var a;try{b({$type:"class"})}catch(e_){a=e_}assert(a instanceof gpf.Error.MissingEntityName)}),it("validates minimal requirement (type and name)",function(){b({$type:"class",$name:"Test"})}),it("rejects invalid properties",function(){var a;try{b({$type:"class",$name:"Test",$fail:!0})}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidEntity$Property)}),it("converts $class into _type and _name",function(){var c=b({$class:"Test"});assert(c instanceof a),assert("class"===c._type),assert("Test"===c._name)}),it("converts $class into _type, _name and _namespace (absolute)",function(){var a=b({$class:"gpf.test.Test"});assert("class"===a._type),assert("Test"===a._name),assert("gpf.test"===a._namespace)}),it("converts $class into _type, _name and _namespace (relative)",function(){var a=b({$class:"test.Test",$namespace:"gpf"});assert("class"===a._type),assert("Test"===a._name),assert("gpf.test"===a._namespace)}),it("prioritize $class over $name",function(){var a=b({$class:"Test",$name:"Any"});assert("class"===a._type),assert("Test"===a._name)}),it("validates namespace",function(){b({$class:"Test",$namespace:"lowerCamelCase.$accepted._also.numbers456"}),b({$class:"Test",$namespace:"simple"}),b({$class:"Test",$namespace:""})}),["endingPointIsNotOK.","startingNumberIsNotOK.4test","$isOKOnlyAtBeginning.test$","_isOKOnlyAtBeginning.test_","CapitalFirstLetterIsNotOK"].forEach(function(a){it("rejects invalid namespace ("+a+")",function(){var c;try{b({$class:"Test",$namespace:a})}catch(e_){c=e_}assert(c instanceof gpf.Error.InvalidEntityNamespace)})})})}),describe("define/class/check",function(){gpf.internals&&describe("(internal) _GpfClassDefinition",function(){var a=gpf.internals._GpfClassDefinition,b=gpf.internals._gpfDefineBuildTypedEntity;it("is used for class definition",function(){var c=b({$class:"Test"});assert(c instanceof a)}),it("accepts a valid class definition",function(){b({$class:"Test",member:function(){}})}),["startingWithLowercaseLetterIsNotOK","The$signIsForbbidenIfNotAtTheBeginning","The_signIsForbbidenIfNotAtTheBeginning"].forEach(function(a){it("rejects invalid class name ("+a+")",function(){var c;try{b({$class:a})}catch(e_){c=e_}assert(c instanceof gpf.Error.InvalidClassName)})}),["StartingWithUppercaseLetterIsNotOK","the$signIsForbbidenIfNotAtTheBeginning","the_signIsForbbidenIfNotAtTheBeginning","class"].forEach(function(a){it("rejects invalid property name ("+a+")",function(){var c,d={$class:"Test"};d[a]=!0;try{b(d)}catch(e_){c=e_}assert(c instanceof gpf.Error.InvalidClassProperty)})}),it("rejects invalid $extend",function(){var a;try{b({$class:"Test",$extend:12})}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidClassExtend)}),it("accepts native $extend",function(){b({$class:"Test",$extend:String})}),it("accepts contextual $extend",function(){b({$class:"Test",$extend:"String"})})})}),describe("define",function(){var a={};before(function(){gpf.context().test=a}),after(function(){delete gpf.context().test}),describe("gpf.define",function(){it("accepts only one parameter",function(){assert("function"==typeof gpf.define),assert(1===gpf.define.length)}),describe("Simple class description",function(){describe("Validation",function(){it("checks that he entity type is specified",function(){var a;try{gpf.define({})}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidEntityType)}),["1NumberAtTheBeginningIsNotOK","noUppercaseFirstLetterIsNotOK","DollarSignAnywhereIsNotOK$"].forEach(function(a){it("rejects invalid class name ("+a+")",function(){var b;try{gpf.define({$class:a})}catch(e_){b=e_}assert(b instanceof gpf.Error.InvalidClassName)})}),["A","$B","_C","Test123"].forEach(function(a){it("validates class name ("+a+")",function(){var b;try{gpf.define({$class:a})}catch(e_){b=e_}assert(void 0===b)})}),it("rejects invalid $ property names",function(){var a;try{gpf.define({$class:"Test",$test:!1})}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidEntity$Property)}),it("rejects invalid property names (reserved keywords)",function(){var a;try{gpf.define({$class:"Test","super":!1})}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidClassProperty)}),it("rejects constructor property if not a method",function(){var a;try{gpf.define({$class:"Test",constructor:!1})}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidClassConstructor)})})}),describe("Definition",function(){var b,c;before(function(){b=gpf.define({$class:"A",_member:"defaultValue",getMember:function(){return this._member},"constructor":function(a){a&&(this._member=a),this._constructorOfA=!0},funcWith3params:function(a,b,c){return a+b+c},throwError:function(){throw new Error("error")}}),c=new b}),it("prevents constructor functions to be used without new",function(){var a;try{b()}catch(e_){a=e_}assert(a instanceof gpf.Error.ClassConstructorFunction)}),it("creates a constructor with the same signature than the constructor property",function(){assert(1===b.length)}),it("handles instanceof",function(){assert(c instanceof b)}),it("calls constructor property",function(){assert(c._constructorOfA)}),it("exposes methods",function(){assert("function"==typeof c.getMember),assert("defaultValue"===c.getMember())}),describe("Subclassing",function(){it("prevents invalid override",function(){var a;try{gpf.define({$class:"Test",$extend:b,getMember:!1})}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidClassOverride)});var c,d;before(function(){c=gpf.define({$class:"test.B",$extend:b,"constructor":function(a){this.$super("valueOfB"),this._constructorOfB=a},getMember:function(){return this.$super()+"-inB"},setMember:function(a){this._member=a},baseTest:function(){return this.$super.getMember()},invalidSuperMember:function(){return this.$super.doesntExist()},noSuperMember:function(){return this.$super()},differentBinding:function(){return this.$super.getMember.call({_member:"different"})},checkSignature:function(){assert(3===this.$super.funcWith3params.length)},throwError:function(){this.$super()}}),d=new c(3475)}),it("handles instanceof",function(){assert(d instanceof b),assert(d instanceof c)}),it("handles namespace",function(){assert(a.B===c)}),it("calls the constructor function",function(){assert(3475===d._constructorOfB)}),it("calls the proper $super()",function(){assert(d._constructorOfA),assert("valueOfB-inB"===d.getMember())}),it("offers a way to call named base method",function(){assert("valueOfB"===d.baseTest())}),it("fails when accessing an unknown $super member",function(){var a;try{d.invalidSuperMember()}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidClassSuperMember)}),it("fails when accessing inexistent $super",function(){var a;try{d.noSuperMember()}catch(e_){a=e_}assert(a instanceof gpf.Error.InvalidClassSuper)}),it("allows calling $super member with a different binding",function(){assert("different"===d.differentBinding())}),it("respects methods signature",function(){d.checkSignature()}),it("does not leak $super",function(){assert(void 0===d.$super)}),it("does not leak $super on exception",function(){try{d.throwError()}catch(e_){}assert(void 0===d.$super)}),it("handles several versions of $super",function(){var a=gpf.define({$class:"C",$extend:c,testMethod:function(){return this.$super.getMember()}}),b=new a;assert("valueOfB-inB"===b.testMethod())})})})})}); \ No newline at end of file diff --git a/package.json b/package.json index 9e9da8dd..819b3172 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gpf-js", - "version": "0.1.7-alpha", + "version": "0.1.7", "description": "A multi-purpose JavaScript library", "main": "build/gpf.js", "directories": { diff --git a/src/boot.js b/src/boot.js index 2a41b587..9a9822bd 100644 --- a/src/boot.js +++ b/src/boot.js @@ -33,7 +33,7 @@ var * GPF Version * @since 0.1.5 */ - _gpfVersion = "0.1.7-alpha", + _gpfVersion = "0.1.7", /** * Host constants