diff options
Diffstat (limited to 'tools/addon-sdk-1.7/packages/api-utils/lib/base.js')
-rw-r--r-- | tools/addon-sdk-1.7/packages/api-utils/lib/base.js | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/tools/addon-sdk-1.7/packages/api-utils/lib/base.js b/tools/addon-sdk-1.7/packages/api-utils/lib/base.js new file mode 100644 index 0000000..63acabc --- /dev/null +++ b/tools/addon-sdk-1.7/packages/api-utils/lib/base.js @@ -0,0 +1,177 @@ +/* vim:set ts=2 sw=2 sts=2 expandtab */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +// Instead of inheriting from `Object.prototype` we copy all interesting +// properties from it and then freeze. This way we can guarantee integrity +// of components build on top. +exports.Base = Object.freeze(Object.create(null, { + toString: { value: Object.prototype.toString }, + toLocaleString: { value: Object.prototype.toLocaleString }, + toSource: { value: Object.prototype.toSource }, + valueOf: { value: Object.prototype.valueOf }, + isPrototypeOf: { value: Object.prototype.isPrototypeOf }, + /** + * Creates an object that inherits from `this` object (Analog of + * `new Object()`). + * @examples + * + * var Dog = Base.extend({ + * bark: function bark() { + * return 'Ruff! Ruff!' + * } + * }); + * var dog = Dog.new(); + */ + new: { value: function create() { + var object = Object.create(this); + object.initialize.apply(object, arguments); + return object; + }}, + /** + * When new instance of the this prototype is created it's `initialize` + * method is called with all the arguments passed to the `new`. You can + * override `initialize` to set up an instance. + */ + initialize: { value: function initialize() { + }}, + /** + * Merges all the properties of the passed objects into `this` instance (This + * method can be used on instances only as prototype objects are frozen). + * + * If two or more argument objects have own properties with the same name, + * the property is overridden, with precedence from right to left, implying, + * that properties of the object on the left are overridden by a same named + * property of the object on the right. + * + * @examples + * + * var Pet = Dog.extend({ + * initialize: function initialize(options) { + * // this.name = options.name -> would have thrown (frozen prototype) + * this.merge(options) // will override all properties. + * }, + * call: function(name) { + * return this.name === name ? this.bark() : '' + * }, + * name: null + * }) + * var pet = Pet.new({ name: 'Benzy', breed: 'Labrador' }) + * pet.call('Benzy') // 'Ruff! Ruff!' + */ + merge: { value: function merge() { + var descriptor = {}; + Array.prototype.forEach.call(arguments, function (properties) { + Object.getOwnPropertyNames(properties).forEach(function(name) { + descriptor[name] = Object.getOwnPropertyDescriptor(properties, name); + }); + }); + Object.defineProperties(this, descriptor); + return this; + }}, + /** + * Takes any number of argument objects and returns frozen, composite object + * that inherits from `this` object and combines all of the own properties of + * the argument objects. (Objects returned by this function are frozen as + * they are intended to be used as types). + * + * If two or more argument objects have own properties with the same name, + * the property is overridden, with precedence from right to left, implying, + * that properties of the object on the left are overridden by a same named + * property of the object on the right. + * @examples + * + * // ## Object composition ## + * + * var HEX = Base.extend({ + * hex: function hex() { + * return '#' + this.color; + * } + * }) + * + * var RGB = Base.extend({ + * red: function red() { + * return parseInt(this.color.substr(0, 2), 16); + * }, + * green: function green() { + * return parseInt(this.color.substr(2, 2), 16); + * }, + * blue: function blue() { + * return parseInt(this.color.substr(4, 2), 16); + * } + * }) + * + * var CMYK = Base.extend(RGB, { + * black: function black() { + * var color = Math.max(Math.max(this.red(), this.green()), this.blue()); + * return (1 - color / 255).toFixed(4); + * }, + * cyan: function cyan() { + * var K = this.black(); + * return (((1 - this.red() / 255).toFixed(4) - K) / (1 - K)).toFixed(4); + * }, + * magenta: function magenta() { + * var K = this.black(); + * return (((1 - this.green() / 255).toFixed(4) - K) / (1 - K)).toFixed(4); + * }, + * yellow: function yellow() { + * var K = this.black(); + * return (((1 - this.blue() / 255).toFixed(4) - K) / (1 - K)).toFixed(4); + * } + * }) + * + * var Color = Base.extend(HEX, RGB, CMYK, { + * initialize: function Color(color) { + * this.color = color; + * } + * }); + * + * // ## Prototypal inheritance ## + * + * var Pixel = Color.extend({ + * initialize: function Pixel(x, y, hex) { + * Color.initialize.call(this, hex); + * this.x = x; + * this.y = y; + * }, + * toString: function toString() { + * return this.x + ':' + this.y + '@' + this.hex(); + * } + * }); + * + * var pixel = Pixel.new(11, 23, 'CC3399') + * pixel.toString(); // 11:23@#CC3399 + * + * pixel.red(); // 204 + * pixel.green(); // 51 + * pixel.blue(); // 153 + * + * pixel.cyan(); // 0.0000 + * pixel.magenta(); // 0.7500 + * pixel.yellow(); // 0.2500 + * + */ + extend: { value: function extend() { + return Object.freeze(this.merge.apply(Object.create(this), arguments)); + }} +})); + +/** + * Function takes prototype object that implements `initialize` method, and + * returns `constructor` function (with correct prototype property), that can + * be used for simulating classes for given prototypes. + */ +exports.Class = Object.freeze(function Class(prototype) { + function constructor() { + var instance = Object.create(prototype); + prototype.initialize.apply(instance, arguments); + return instance; + } + return Object.freeze(Object.defineProperties(constructor, { + prototype: { value: prototype }, + new: { value: constructor } + })); +}); |