addon-sdk/source/lib/sdk/deprecated/traits.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/addon-sdk/source/lib/sdk/deprecated/traits.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,187 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +"use strict";
     1.9 +
    1.10 +module.metadata = {
    1.11 +  "stability": "deprecated"
    1.12 +};
    1.13 +
    1.14 +const {
    1.15 +  compose: _compose,
    1.16 +  override: _override,
    1.17 +  resolve: _resolve,
    1.18 +  trait: _trait,
    1.19 +  //create: _create,
    1.20 +  required,
    1.21 +} = require('./traits/core');
    1.22 +
    1.23 +const defineProperties = Object.defineProperties,
    1.24 +      freeze = Object.freeze,
    1.25 +      create = Object.create;
    1.26 +
    1.27 +/**
    1.28 + * Work around bug 608959 by defining the _create function here instead of
    1.29 + * importing it from traits/core.  For docs on this function, see the create
    1.30 + * function in that module.
    1.31 + *
    1.32 + * FIXME: remove this workaround in favor of importing the function once that
    1.33 + * bug has been fixed.
    1.34 + */
    1.35 +function _create(proto, trait) {
    1.36 +  let properties = {},
    1.37 +      keys = Object.getOwnPropertyNames(trait);
    1.38 +  for each(let key in keys) {
    1.39 +    let descriptor = trait[key];
    1.40 +    if (descriptor.required &&
    1.41 +        !Object.prototype.hasOwnProperty.call(proto, key))
    1.42 +      throw new Error('Missing required property: ' + key);
    1.43 +    else if (descriptor.conflict)
    1.44 +      throw new Error('Remaining conflicting property: ' + key);
    1.45 +    else
    1.46 +      properties[key] = descriptor;
    1.47 +  }
    1.48 +  return Object.create(proto, properties);
    1.49 +}
    1.50 +
    1.51 +/**
    1.52 + * Placeholder for `Trait.prototype`
    1.53 + */
    1.54 +let TraitProto = Object.prototype;
    1.55 +
    1.56 +function Get(key) this[key]
    1.57 +function Set(key, value) this[key] = value
    1.58 +
    1.59 +/**
    1.60 + * Creates anonymous trait descriptor from the passed argument, unless argument
    1.61 + * is a trait constructor. In later case trait's already existing properties
    1.62 + * descriptor is returned.
    1.63 + * This is module's internal function and is used as a gateway to a trait's
    1.64 + * internal properties descriptor.
    1.65 + * @param {Function} $
    1.66 + *    Composed trait's constructor.
    1.67 + * @returns {Object}
    1.68 + *    Private trait property of the composition.
    1.69 + */
    1.70 +function TraitDescriptor(object)
    1.71 +  (
    1.72 +    'function' == typeof object &&
    1.73 +    (object.prototype == TraitProto || object.prototype instanceof Trait)
    1.74 +  ) ? object._trait(TraitDescriptor) : _trait(object)
    1.75 +
    1.76 +function Public(instance, trait) {
    1.77 +  let result = {},
    1.78 +      keys = Object.getOwnPropertyNames(trait);
    1.79 +  for each (let key in keys) {
    1.80 +    if ('_' === key.charAt(0) && '__iterator__' !== key )
    1.81 +      continue;
    1.82 +    let property = trait[key],
    1.83 +        descriptor = {
    1.84 +          configurable: property.configurable,
    1.85 +          enumerable: property.enumerable
    1.86 +        };
    1.87 +    if (property.get)
    1.88 +      descriptor.get = property.get.bind(instance);
    1.89 +    if (property.set)
    1.90 +      descriptor.set = property.set.bind(instance);
    1.91 +    if ('value' in property) {
    1.92 +      let value = property.value;
    1.93 +      if ('function' === typeof value) {
    1.94 +        descriptor.value = property.value.bind(instance);
    1.95 +        descriptor.writable = property.writable;
    1.96 +      } else {
    1.97 +        descriptor.get = Get.bind(instance, key);
    1.98 +        descriptor.set = Set.bind(instance, key);
    1.99 +      }
   1.100 +    }
   1.101 +    result[key] = descriptor;
   1.102 +  }
   1.103 +  return result;
   1.104 +}
   1.105 +
   1.106 +/**
   1.107 + * This is private function that composes new trait with privates.
   1.108 + */
   1.109 +function Composition(trait) {
   1.110 +  function Trait() {
   1.111 +    let self = _create({}, trait);
   1.112 +    self._public = create(Trait.prototype, Public(self, trait));
   1.113 +    delete self._public.constructor;
   1.114 +    if (Object === self.constructor)
   1.115 +      self.constructor = Trait;
   1.116 +    else
   1.117 +      return self.constructor.apply(self, arguments) || self._public;
   1.118 +    return self._public;
   1.119 +  }
   1.120 +  defineProperties(Trait, {
   1.121 +    prototype: { value: freeze(create(TraitProto, {
   1.122 +      constructor: { value: constructor, writable: true }
   1.123 +    }))}, // writable is `true` to avoid getters in custom ES5
   1.124 +    displayName: { value: (trait.constructor || constructor).name },
   1.125 +    compose: { value: compose, enumerable: true },
   1.126 +    override: { value: override, enumerable: true },
   1.127 +    resolve: { value: resolve, enumerable: true },
   1.128 +    required: { value: required, enumerable: true },
   1.129 +    _trait: { value: function _trait(caller)
   1.130 +        caller ===  TraitDescriptor ? trait : undefined
   1.131 +    }
   1.132 +  });
   1.133 +  return freeze(Trait);
   1.134 +}
   1.135 +
   1.136 +/**
   1.137 + * Composes new trait out of itself and traits / property maps passed as an
   1.138 + * arguments. If two or more traits / property maps have properties with the
   1.139 + * same name, the new trait will contain a "conflict" property for that name.
   1.140 + * This is a commutative and associative operation, and the order of its
   1.141 + * arguments is not significant.
   1.142 + * @params {Object|Function}
   1.143 + *    List of Traits or property maps to create traits from.
   1.144 + * @returns {Function}
   1.145 + *    New trait containing the combined properties of all the traits.
   1.146 + */
   1.147 +function compose() {
   1.148 +  let traits = Array.slice(arguments, 0);
   1.149 +  traits.push(this);
   1.150 +  return Composition(_compose.apply(null, traits.map(TraitDescriptor)));
   1.151 +}
   1.152 +
   1.153 +/**
   1.154 + * Composes a new trait with all of the combined properties of `this` and the
   1.155 + * argument traits. In contrast to `compose`, `override` immediately resolves
   1.156 + * all conflicts resulting from this composition by overriding the properties of
   1.157 + * later traits. Trait priority is from left to right. I.e. the properties of
   1.158 + * the leftmost trait are never overridden.
   1.159 + * @params {Object} trait
   1.160 + * @returns {Object}
   1.161 + */
   1.162 +function override() {
   1.163 +  let traits = Array.slice(arguments, 0);
   1.164 +  traits.push(this);
   1.165 +  return Composition(_override.apply(null, traits.map(TraitDescriptor)));
   1.166 +}
   1.167 +
   1.168 +/**
   1.169 + * Composes new resolved trait, with all the same properties as this
   1.170 + * trait, except that all properties whose name is an own property of
   1.171 + * `resolutions` will be renamed to `resolutions[name]`. If it is
   1.172 + * `resolutions[name]` is `null` value is changed into a required property
   1.173 + * descriptor.
   1.174 + */
   1.175 +function resolve(resolutions)
   1.176 +  Composition(_resolve(resolutions, TraitDescriptor(this)))
   1.177 +
   1.178 +/**
   1.179 + * Base Trait, that all the traits are composed of.
   1.180 + */
   1.181 +const Trait = Composition({
   1.182 +  /**
   1.183 +   * Internal property holding public API of this instance.
   1.184 +   */
   1.185 +  _public: { value: null, configurable: true, writable: true },
   1.186 +  toString: { value: function() '[object ' + this.constructor.name + ']' }
   1.187 +});
   1.188 +TraitProto = Trait.prototype;
   1.189 +exports.Trait = Trait;
   1.190 +

mercurial