UNPKG

arcade-physics

Version:
181 lines 6.33 kB
"use strict"; /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2020 Photon Storm Ltd. * @license {@link https://opensource.org/licenses/MIT|MIT License} */ Object.defineProperty(exports, "__esModule", { value: true }); // Taken from klasse by mattdesl https://github.com/mattdesl/klasse function hasGetterOrSetter(def) { return (!!def.get && typeof def.get === 'function') || (!!def.set && typeof def.set === 'function'); } function getProperty(definition, k, isClassDescriptor) { // This may be a lightweight object, OR it might be a property that was defined previously. // For simple class descriptors we can just assume its NOT previously defined. let def = isClassDescriptor ? definition[k] : Object.getOwnPropertyDescriptor(definition, k); if (!isClassDescriptor && def.value && typeof def.value === 'object') { def = def.value; } // This might be a regular property, or it may be a getter/setter the user defined in a class. if (def && hasGetterOrSetter(def)) { if (typeof def.enumerable === 'undefined') { def.enumerable = true; } if (typeof def.configurable === 'undefined') { def.configurable = true; } return def; } else { return false; } } function hasNonConfigurable(obj, k) { let prop = Object.getOwnPropertyDescriptor(obj, k); if (!prop) { return false; } if (prop.value && typeof prop.value === 'object') { prop = prop.value; } if (prop.configurable === false) { return true; } return false; } /** * Extends the given `myClass` object's prototype with the properties of `definition`. * * @function extend * @ignore * @param {Object} ctor The constructor object to mix into. * @param {Object} definition A dictionary of functions for the class. * @param {boolean} isClassDescriptor Is the definition a class descriptor? * @param {Object} [extend] The parent constructor object. */ function extend(ctor, definition, isClassDescriptor, extend) { for (const k in definition) { if (!definition.hasOwnProperty(k)) { continue; } const def = getProperty(definition, k, isClassDescriptor); if (def !== false) { // If Extends is used, we will check its prototype to see if the final variable exists. const parent = extend || ctor; if (hasNonConfigurable(parent.prototype, k)) { // Just skip the final property if (Class.ignoreFinals) { continue; } // We cannot re-define a property that is configurable=false. // So we will consider them final and throw an error. This is by // default so it is clear to the developer what is happening. // You can set ignoreFinals to true if you need to extend a class // which has configurable=false; it will simply not re-define final properties. throw new Error(`cannot override final property '${k}', set Class.ignoreFinals = true to skip`); } Object.defineProperty(ctor.prototype, k, def); } else { ctor.prototype[k] = definition[k]; } } } /** * Applies the given `mixins` to the prototype of `myClass`. * * @function mixin * @ignore * @param {Object} myClass The constructor object to mix into. * @param {Object|Array<Object>} mixins The mixins to apply to the constructor. */ function mixin(myClass, mixins) { if (!mixins) { return; } if (!Array.isArray(mixins)) { mixins = [mixins]; } for (let i = 0; i < mixins.length; i++) { extend(myClass, mixins[i].prototype || mixins[i]); } } /** * Creates a new class with the given descriptor. * The constructor, defined by the name `initialize`, * is an optional function. If unspecified, an anonymous * function will be used which calls the parent class (if * one exists). * * You can also use `Extends` and `Mixins` to provide subclassing * and inheritance. * * @class Phaser.Class * @constructor * @param {Object} definition a dictionary of functions for the class * @example * * var MyClass = new Phaser.Class({ * * initialize: function() { * this.foo = 2.0; * }, * * bar: function() { * return this.foo + 5; * } * }); */ function Class(definition) { if (!definition) { definition = {}; } // The variable name here dictates what we see in Chrome debugger let initialize; let Extends; if (definition.initialize) { if (typeof definition.initialize !== 'function') { throw new Error('initialize must be a function'); } initialize = definition.initialize; // Usually we should avoid 'delete' in V8 at all costs. // However, its unlikely to make any performance difference // here since we only call this on class creation (i.e. not object creation). delete definition.initialize; } else if (definition.Extends) { const base = definition.Extends; initialize = function () { base.apply(this, arguments); }; } else { initialize = () => { }; } if (definition.Extends) { initialize.prototype = Object.create(definition.Extends.prototype); initialize.prototype.constructor = initialize; // For getOwnPropertyDescriptor to work, we need to act directly on the Extends (or Mixin) Extends = definition.Extends; delete definition.Extends; } else { initialize.prototype.constructor = initialize; } // Grab the mixins, if they are specified... let mixins = null; if (definition.Mixins) { mixins = definition.Mixins; delete definition.Mixins; } // First, mixin if we can. mixin(initialize, mixins); // Now we grab the actual definition which defines the overrides. extend(initialize, definition, true, Extends); return initialize; } Class.extend = extend; Class.mixin = mixin; Class.ignoreFinals = false; exports.default = Class; //# sourceMappingURL=Class.js.map