UNPKG

@phosphor/properties

Version:
191 lines (190 loc) 6.41 kB
"use strict"; /*----------------------------------------------------------------------------- | Copyright (c) 2014-2017, PhosphorJS Contributors | | Distributed under the terms of the BSD 3-Clause License. | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ Object.defineProperty(exports, "__esModule", { value: true }); /** * A class which attaches a value to an external object. * * #### Notes * Attached properties are used to extend the state of an object with * semantic data from an unrelated class. They also encapsulate value * creation, coercion, and notification. * * Because attached property values are stored in a hash table, which * in turn is stored in a WeakMap keyed on the owner object, there is * non-trivial storage overhead involved in their use. The pattern is * therefore best used for the storage of rare data. */ var AttachedProperty = /** @class */ (function () { /** * Construct a new attached property. * * @param options - The options for initializing the property. */ function AttachedProperty(options) { this._pid = Private.nextPID(); this.name = options.name; this._create = options.create; this._coerce = options.coerce || null; this._compare = options.compare || null; this._changed = options.changed || null; } /** * Get the current value of the property for a given owner. * * @param owner - The property owner of interest. * * @returns The current value of the property. * * #### Notes * If the value has not yet been set, the default value will be * computed and assigned as the current value of the property. */ AttachedProperty.prototype.get = function (owner) { var value; var map = Private.ensureMap(owner); if (this._pid in map) { value = map[this._pid]; } else { value = map[this._pid] = this._createValue(owner); } return value; }; /** * Set the current value of the property for a given owner. * * @param owner - The property owner of interest. * * @param value - The value for the property. * * #### Notes * If the value has not yet been set, the default value will be * computed and used as the previous value for the comparison. */ AttachedProperty.prototype.set = function (owner, value) { var oldValue; var map = Private.ensureMap(owner); if (this._pid in map) { oldValue = map[this._pid]; } else { oldValue = map[this._pid] = this._createValue(owner); } var newValue = this._coerceValue(owner, value); this._maybeNotify(owner, oldValue, map[this._pid] = newValue); }; /** * Explicitly coerce the current property value for a given owner. * * @param owner - The property owner of interest. * * #### Notes * If the value has not yet been set, the default value will be * computed and used as the previous value for the comparison. */ AttachedProperty.prototype.coerce = function (owner) { var oldValue; var map = Private.ensureMap(owner); if (this._pid in map) { oldValue = map[this._pid]; } else { oldValue = map[this._pid] = this._createValue(owner); } var newValue = this._coerceValue(owner, oldValue); this._maybeNotify(owner, oldValue, map[this._pid] = newValue); }; /** * Get or create the default value for the given owner. */ AttachedProperty.prototype._createValue = function (owner) { var create = this._create; return create(owner); }; /** * Coerce the value for the given owner. */ AttachedProperty.prototype._coerceValue = function (owner, value) { var coerce = this._coerce; return coerce ? coerce(owner, value) : value; }; /** * Compare the old value and new value for equality. */ AttachedProperty.prototype._compareValue = function (oldValue, newValue) { var compare = this._compare; return compare ? compare(oldValue, newValue) : oldValue === newValue; }; /** * Run the change notification if the given values are different. */ AttachedProperty.prototype._maybeNotify = function (owner, oldValue, newValue) { var changed = this._changed; if (changed && !this._compareValue(oldValue, newValue)) { changed(owner, oldValue, newValue); } }; return AttachedProperty; }()); exports.AttachedProperty = AttachedProperty; /** * The namespace for the `AttachedProperty` class statics. */ (function (AttachedProperty) { /** * Clear the stored property data for the given owner. * * @param owner - The property owner of interest. * * #### Notes * This will clear all property values for the owner, but it will * **not** run the change notification for any of the properties. */ function clearData(owner) { Private.ownerData.delete(owner); } AttachedProperty.clearData = clearData; })(AttachedProperty = exports.AttachedProperty || (exports.AttachedProperty = {})); exports.AttachedProperty = AttachedProperty; /** * The namespace for the module implementation details. */ var Private; (function (Private) { /** * A weak mapping of property owner to property map. */ Private.ownerData = new WeakMap(); /** * A function which computes successive unique property ids. */ Private.nextPID = (function () { var id = 0; return function () { var rand = Math.random(); var stem = ("" + rand).slice(2); return "pid-" + stem + "-" + id++; }; })(); /** * Lookup the data map for the property owner. * * This will create the map if one does not already exist. */ function ensureMap(owner) { var map = Private.ownerData.get(owner); if (map) { return map; } map = Object.create(null); Private.ownerData.set(owner, map); return map; } Private.ensureMap = ensureMap; })(Private || (Private = {}));