aboutsummaryrefslogtreecommitdiff
path: root/tools/addon-sdk-1.7/packages/api-utils/docs/light-traits.md
diff options
context:
space:
mode:
Diffstat (limited to 'tools/addon-sdk-1.7/packages/api-utils/docs/light-traits.md')
-rw-r--r--tools/addon-sdk-1.7/packages/api-utils/docs/light-traits.md295
1 files changed, 295 insertions, 0 deletions
diff --git a/tools/addon-sdk-1.7/packages/api-utils/docs/light-traits.md b/tools/addon-sdk-1.7/packages/api-utils/docs/light-traits.md
new file mode 100644
index 0000000..367a6a9
--- /dev/null
+++ b/tools/addon-sdk-1.7/packages/api-utils/docs/light-traits.md
@@ -0,0 +1,295 @@
+<!-- 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/. -->
+
+
+[Traits](http://en.wikipedia.org/wiki/Trait_%28computer_science%29) are a simple
+mechanism for structuring object-oriented programs. They represent reusable and
+composable building blocks of functionality that factor out the common
+attributes and behavior of objects.
+
+They are a more robust alternative to
+[mixins](http://en.wikipedia.org/wiki/Mixins) and
+[multiple inheritance](http://en.wikipedia.org/wiki/Multiple_inheritance),
+because name clashes must be explicitly resolved and composition is commutative
+and associative (i.e. the order of traits in a composition is irrelevant).
+
+Use traits to share functionality between similar objects without duplicating
+code or creating complex inheritance chains.
+
+## Trait Creation ##
+
+To create a trait, call the `Trait` constructor function exported by this
+module, passing it a JavaScript object that specifies the properties of the
+trait.
+
+ let Trait = require('light-traits').Trait;
+ let t = Trait({
+ foo: "foo",
+ bar: function bar() {
+ return "Hi!"
+ },
+ baz: Trait.required
+ });
+
+Traits can both provide and require properties. A *provided* property is a
+property for which the trait itself provides a value. A *required* property is a
+property that the trait needs in order to function correctly but for which
+it doesn't provide a value.
+
+Required properties must be provided by another trait or by an object with a
+trait. Creation of an object with a trait will fail if required properties are
+not provided. Specify a required property by setting the value of the property
+to `Trait.required`.
+
+## Object Creation ##
+
+Create objects with a single trait by calling the trait's `create` method. The
+method takes a single argument, the object to serve as the new object's
+prototype. If no prototype is specified, the new object's prototype will be
+`Object.prototype`.
+
+ let t = Trait({
+ foo: 'foo',
+ bar: 2
+ });
+ let foo1 = t.create();
+ let foo2 = t.create({ name: 'Super' });
+
+## Trait Composition ##
+
+Traits are designed to be composed with other traits to create objects with the
+properties of multiple traits. To compose an object with multiple traits, you
+first create a composite trait and then use it to create the object. A composite
+trait is a trait that contains all of the properties of the traits from which it
+is composed. In the following example, MagnitudeTrait is a composite trait.
+
+ let EqualityTrait = Trait({
+ equal: Trait.required,
+ notEqual: function notEqual(x) {
+ return !this.equal(x)
+ }
+ });
+
+ let ComparisonTrait = Trait({
+ less: Trait.required,
+ notEqual: Trait.required,
+ greater: function greater(x) {
+ return !this.less(x) && this.notEqual(x)
+ }
+ });
+
+ let MagnitudeTrait = Trait.compose(EqualityTrait, ComparisonTrait);
+
+<?xml version="1.0"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="-11 121 490 190" width="490px" height="190px">
+ <defs>
+ <marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="SharpArrow_Marker" viewBox="-4 -4 10 8" markerWidth="10" markerHeight="8" color="black">
+ <g>
+ <path d="M 5 0 L -3 -3 L 0 0 L 0 0 L -3 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1px"/>
+ </g>
+ </marker>
+ </defs>
+ <g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1">
+ <g>
+ <rect x="9" y="165.33334" width="141" height="14"/>
+ <rect x="9" y="165.33334" width="141" height="14" stroke="black" stroke-width="1px"/>
+ <text transform="translate(14 165.33334)" fill="black">
+ <tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="11" textLength="47.373047">notEqual</tspan>
+ </text>
+ <rect x="9" y="151.33334" width="141" height="14"/>
+ <rect x="9" y="151.33334" width="141" height="14" stroke="black" stroke-width="1px"/>
+ <text transform="translate(14 151.33334)" fill="red">
+ <tspan font-family="Helvetica" font-size="12" font-weight="500" fill="red" x="0" y="11" textLength="29.361328">equal</tspan>
+ </text>
+ <rect x="9" y="137.33334" width="141" height="14"/>
+ <rect x="9" y="137.33334" width="141" height="14" stroke="black" stroke-width="1px"/>
+ <text transform="translate(14 137.33334)" fill="black">
+ <tspan font-family="Helvetica" font-size="12" font-weight="bold" x="38.49707" y="11" textLength="54.00586">EqualityTrait</tspan>
+ </text>
+ <rect x="9" y="273" width="141" height="14"/>
+ <rect x="9" y="273" width="141" height="14" stroke="black" stroke-width="1px"/>
+ <text transform="translate(14 273)" fill="black">
+ <tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="11" textLength="38.021484">greater</tspan>
+ </text>
+ <rect x="9" y="259" width="141" height="14"/>
+ <rect x="9" y="259" width="141" height="14" stroke="black" stroke-width="1px"/>
+ <text transform="translate(14 259)" fill="red">
+ <tspan font-family="Helvetica" font-size="12" font-weight="500" fill="red" x="0" y="11" textLength="47.373047">notEqual</tspan>
+ </text>
+ <rect x="9" y="245" width="141" height="14"/>
+ <rect x="9" y="245" width="141" height="14" stroke="black" stroke-width="1px"/>
+ <text transform="translate(14 245)" fill="red">
+ <tspan font-family="Helvetica" font-size="12" font-weight="500" fill="red" x="0" y="11" textLength="21.339844">less</tspan>
+ </text>
+ <rect x="9" y="231" width="141" height="14"/>
+ <rect x="9" y="231" width="141" height="14" stroke="black" stroke-width="1px"/>
+ <text transform="translate(14 231)" fill="black">
+ <tspan font-family="Helvetica" font-size="12" font-weight="bold" x=".15332031" y="11" textLength="112.67578">ComparisonTrait</tspan>
+ </text>
+ <rect x="317.75" y="235.5" width="141" height="14"/>
+ <rect x="317.75" y="235.5" width="141" height="14" stroke="black" stroke-width="1px"/>
+ <text transform="translate(322.75 235.5)" fill="black">
+ <tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="11" textLength="38.021484">greater</tspan>
+ </text>
+ <rect x="317.75" y="221.5" width="141" height="14"/>
+ <rect x="317.75" y="221.5" width="141" height="14" stroke="black" stroke-width="1px"/>
+ <text transform="translate(322.75 221.5)" fill="red">
+ <tspan font-family="Helvetica" font-size="12" font-weight="500" fill="red" x="0" y="11" textLength="21.339844">less</tspan>
+ </text>
+ <rect x="317.75" y="207.5" width="141" height="14"/>
+ <rect x="317.75" y="207.5" width="141" height="14" stroke="black" stroke-width="1px"/>
+ <text transform="translate(322.75 207.5)" fill="black">
+ <tspan font-family="Helvetica" font-size="12" font-weight="500" x="0" y="11" textLength="47.373047">notEqual</tspan>
+ </text>
+ <rect x="317.75" y="193.5" width="141" height="14"/>
+ <rect x="317.75" y="193.5" width="141" height="14" stroke="black" stroke-width="1px"/>
+ <text transform="translate(322.75 193.5)" fill="red">
+ <tspan font-family="Helvetica" font-size="12" font-weight="500" fill="red" x="0" y="11" textLength="29.361328">equal</tspan>
+ </text>
+ <rect x="317.75" y="179.5" width="141" height="14"/>
+ <rect x="317.75" y="179.5" width="141" height="14" stroke="black" stroke-width="1px"/>
+ <text transform="translate(322.75 179.5)" fill="black">
+ <tspan font-family="Helvetica" font-size="12" font-weight="bold" x="31.83789" y="11" textLength="67.32422">MagnitudeTrait</tspan>
+ </text>
+ <path d="M 150 248.83887 L 158.89999 248.83887 L 235.9 248.83887 L 235.9 224.66113 L 308.85 224.66113 L 310.85 224.66113" marker-end="url(#SharpArrow_Marker)" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1px"/>
+ <path d="M 150 171.15845 L 158.89999 171.15845 L 233.9 171.15845 L 233.9 201.6749 L 308.85 201.6749 L 310.85 201.6749" marker-end="url(#SharpArrow_Marker)" stroke="black" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="1px"/>
+ </g>
+ </g>
+</svg>
+
+## Trait Resolution ##
+
+Composite traits have conflicts when two of the traits in the composition
+provide properties with the same name but different values (when compared using
+the `===` strict equality operator). In the following example, `TC` has a
+conflict because `T1` and `T2` both define a `foo` property:
+
+ let T1 = Trait({
+ foo: function () {
+ // do something
+ },
+ bar: 'bar',
+ t1: 1
+ });
+
+ let T2 = Trait({
+ foo: function() {
+ // do something else
+ },
+ bar: 'bar',
+ t2: 2
+ });
+
+ let TC = Trait.compose(T1, T2);
+
+Attempting to create an object from a composite trait with conflicts throws a
+`remaining conflicting property` exception. To create objects from such traits,
+you must resolve the conflict.
+
+You do so by excluding or renaming the conflicting property of one of the
+traits. Excluding a property removes it from the composition, so the composition
+only acquires the property from the other trait. Renaming a property gives it a
+new, non-conflicting name at which it can be accessed.
+
+In both cases, you call the `resolve` method on the trait whose property you
+want to exclude or rename, passing it an object. Each key in the object is the
+name of a conflicting property; each value is either `null` to exclude the
+property or a string representing the new name of the property.
+
+For example, the conflict in the previous example could be resolved by excluding
+the `foo` property of the second trait.
+
+ let TC = Trait(T1, T2.resolve({ foo: null }));
+
+It could also be resolved by renaming the `foo` property of the first trait to
+`foo2`:
+
+ let TC = Trait(T1.resolve({ foo: "foo2" }), T2);
+
+When you resolve a conflict, the same-named property of the other trait (the one
+that wasn't excluded or renamed) remains available in the composition under its
+original name.
+
+## Constructor Functions ##
+
+When your code is going to create more than one object with traits, you may want
+to define a constructor function to create them. To do so, create a composite
+trait representing the traits the created objects should have, then define a
+constructor function that creates objects with that trait and whose prototype is
+the prototype of the constructor:
+
+ let PointTrait = Trait.compose(T1, T2, T3);
+ function Point(options) {
+ let point = PointTrait.create(Point.prototype);
+ return point;
+ }
+
+## Property Descriptor Maps ##
+
+Traits are designed to work with the new object manipulation APIs defined in
+[ECMAScript-262, Edition
+5](http://www.ecma-international.org/publications/standards/Ecma-262.htm) (ES5).
+Traits are also property descriptor maps that inherit from `Trait.prototype` to
+expose methods for creating objects and resolving conflicts.
+
+The following trait definition:
+
+ let FooTrait = Trait({
+ foo: "foo",
+ bar: function bar() {
+ return "Hi!"
+ },
+ baz: Trait.required
+ });
+
+Creates the following property descriptor map:
+
+ {
+ foo: {
+ value: 'foo',
+ enumerable: true,
+ configurable: true,
+ writable: true
+ },
+
+ bar: {
+ value: function b() {
+ return 'bar'
+ },
+ enumerable: true,
+ configurable: true,
+ writable: true
+ },
+
+ baz: {
+ get baz() { throw new Error('Missing required property: `baz`') }
+ set baz() { throw new Error('Missing required property: `baz`') }
+ },
+
+ __proto__: Trait.prototype
+ }
+
+Since Traits are also property descriptor maps, they can be used with built-in
+`Object.*` methods that accept such maps:
+
+ Object.create(proto, FooTrait);
+ Object.defineProperties(myObject, FooTrait);
+
+Note that conflicting and required properties won't cause exceptions to be
+thrown when traits are used with the `Object.*` methods, since those methods are
+not aware of those constraints. However, such exceptions will be thrown when the
+property with the conflict or the required but missing property is accessed.
+
+Property descriptor maps can also be used in compositions. This may be useful
+for defining non-enumerable properties, for example:
+
+ let TC = Trait.compose(
+ Trait({ foo: 'foo' }),
+ { bar: { value: 'bar', enumerable: false } }
+ );
+
+_When using property descriptor maps in this way, make sure the map is not the
+only argument to `Trait.compose`, since in that case it will be interpreted as
+an object literal with properties to be defined._
+