зеркало из https://github.com/mozilla/gecko-dev.git
336 строки
7.5 KiB
JavaScript
336 строки
7.5 KiB
JavaScript
/* 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";
|
|
|
|
var Trait = require("sdk/deprecated/light-traits").Trait;
|
|
var utils = require("./utils");
|
|
var Data = utils.Data;
|
|
var Method = utils.Method;
|
|
var Accessor = utils.Accessor;
|
|
var Required = utils.Required;
|
|
var Conflict = utils.Conflict;
|
|
|
|
function method() {}
|
|
|
|
exports.Assert = require("./assert").Assert
|
|
exports["test simple composition"] = function(assert) {
|
|
var actual = Trait.compose(
|
|
Trait({ a: 0, b: 1 }),
|
|
{ c: { value: 2 }, d: { value: method, enumerable: true } }
|
|
);
|
|
|
|
var expected = {
|
|
a: Data(0),
|
|
b: Data(1),
|
|
c: Data(2, false, false, false),
|
|
d: Method(method, true, false, false)
|
|
};
|
|
|
|
assert.equalTraits(actual, expected);
|
|
};
|
|
|
|
exports["test composition with conflict"] = function(assert) {
|
|
var actual = Trait.compose(
|
|
Trait({ a: 0, b: 1 }),
|
|
{
|
|
a: {
|
|
value: 2,
|
|
writable: true,
|
|
configurable: true,
|
|
enumerable: true
|
|
},
|
|
c: {
|
|
value: method,
|
|
configurable: true
|
|
}
|
|
}
|
|
);
|
|
|
|
var expected = {
|
|
a: Conflict("a"),
|
|
b: Data(1),
|
|
c: Method(method, false, true, false)
|
|
};
|
|
|
|
assert.equalTraits(actual, expected);
|
|
};
|
|
|
|
exports["test identical props does not cause conflict"] = function(assert) {
|
|
var actual = Trait.compose(
|
|
{
|
|
a: {
|
|
value: 0,
|
|
writable: true,
|
|
configurable: true,
|
|
enumerable: true
|
|
},
|
|
b: {
|
|
value: 1
|
|
}
|
|
},
|
|
Trait({
|
|
a: 0,
|
|
c: method
|
|
})
|
|
);
|
|
|
|
var expected = {
|
|
a: Data(0),
|
|
b: Data(1, false, false, false),
|
|
c: Method(method)
|
|
}
|
|
|
|
assert.equalTraits(actual, expected);
|
|
};
|
|
|
|
exports["test composition with identical required props"] = function(assert) {
|
|
var actual = Trait.compose(
|
|
Trait({ a: Trait.required, b: 1 }),
|
|
{ a: { required: true }, c: { value: method } }
|
|
);
|
|
|
|
var expected = {
|
|
a: Required(),
|
|
b: Data(1),
|
|
c: Method(method, false, false, false)
|
|
};
|
|
|
|
assert.equalTraits(actual, expected);
|
|
};
|
|
|
|
exports["test composition satisfying a required prop"] = function(assert) {
|
|
var actual = Trait.compose(
|
|
Trait({ a: Trait.required, b: 1 }),
|
|
{ a: { value: method, enumerable: true } }
|
|
);
|
|
|
|
var expected = {
|
|
a: Method(method, true, false, false),
|
|
b: Data(1)
|
|
};
|
|
|
|
assert.equalTraits(actual, expected);
|
|
};
|
|
|
|
exports["test compose is neutral wrt conflicts"] = function(assert) {
|
|
var actual = Trait.compose(
|
|
Trait({ a: { value: 1 } }, Trait({ a: 2 })),
|
|
{ b: { value: 0, writable: true, configurable: true, enumerable: false } }
|
|
);
|
|
|
|
var expected = { a: Conflict("a"), b: Data(0, false) };
|
|
|
|
assert.equalTraits(actual, expected);
|
|
};
|
|
|
|
exports["test conflicting prop overrides Trait.required"] = function(assert) {
|
|
var actual = Trait.compose(
|
|
Trait.compose(
|
|
Trait({ a: 1 }),
|
|
{ a: { value: 2 } }
|
|
),
|
|
{ a: { value: Trait.required } }
|
|
);
|
|
|
|
var expected = { a: Conflict("a") };
|
|
|
|
assert.equalTraits(actual, expected);
|
|
};
|
|
|
|
exports["test compose is commutative"] = function(assert) {
|
|
var actual = Trait.compose(
|
|
Trait({ a: 0, b: 1 }),
|
|
{ c: { value: 2 }, d: { value: method } }
|
|
);
|
|
|
|
var expected = Trait.compose(
|
|
{ c: { value: 2 }, d: { value: method } },
|
|
Trait({ a: 0, b: 1 })
|
|
);
|
|
|
|
assert.equalTraits(actual, expected);
|
|
}
|
|
|
|
exports["test compose is commutative, also for required/conflicting props"] = function(assert) {
|
|
var actual = Trait.compose(
|
|
{
|
|
a: { value: 0 },
|
|
b: { value: 1 },
|
|
c: { value: 3 },
|
|
e: { value: Trait.required }
|
|
},
|
|
{
|
|
c: { value: 2 },
|
|
d: { get: method }
|
|
}
|
|
);
|
|
|
|
var expected = Trait.compose(
|
|
Trait({ c: 3 }),
|
|
{
|
|
c: { value: 2 },
|
|
d: { get: method },
|
|
a: { value: 0 },
|
|
b: { value: 1 },
|
|
e: { value: Trait.required },
|
|
}
|
|
);
|
|
|
|
assert.equalTraits(actual, expected);
|
|
};
|
|
|
|
exports["test compose is associative"] = function(assert) {
|
|
var actual = Trait.compose(
|
|
{
|
|
a: { value: 0 },
|
|
b: { value: 1 },
|
|
c: { value: 3 },
|
|
d: { value: Trait.required }
|
|
},
|
|
Trait.compose(
|
|
{ c: { value: 3 }, d: { value: Trait.required } },
|
|
{ c: { value: 2 }, d: { value: method }, e: { value: "foo" } }
|
|
)
|
|
);
|
|
|
|
var expected = Trait.compose(
|
|
Trait.compose(
|
|
{
|
|
a: { value: 0 },
|
|
b: { value: 1 },
|
|
c: { value: 3 },
|
|
d: { value: Trait.required }
|
|
},
|
|
{
|
|
c: { value: 3 },
|
|
d: { value: Trait.required }
|
|
}
|
|
),
|
|
{
|
|
c: { value: 2 },
|
|
d: { value: method },
|
|
e: { value: "foo" }
|
|
}
|
|
);
|
|
|
|
assert.equalTraits(actual, expected);
|
|
};
|
|
|
|
exports["test diamond import of same prop do not conflict"] = function(assert) {
|
|
var actual = Trait.compose(
|
|
Trait.compose(
|
|
{ b: { value: 2 } },
|
|
{ a: { value: 1, enumerable: true, configurable: true, writable: true } }
|
|
),
|
|
Trait.compose(
|
|
{ c: { value: 3 } },
|
|
Trait({ a: 1 })
|
|
),
|
|
Trait({ d: 4 })
|
|
);
|
|
|
|
var expected = {
|
|
a: Data(1),
|
|
b: Data(2, false, false, false),
|
|
c: Data(3, false, false, false),
|
|
d: Data(4)
|
|
};
|
|
|
|
assert.equalTraits(actual, expected);
|
|
};
|
|
|
|
exports["test create simple"] = function(assert) {
|
|
var o1 = Trait.compose(
|
|
Trait({ a: 1 }),
|
|
{
|
|
b: {
|
|
value: function() {
|
|
return this.a;
|
|
}
|
|
}
|
|
}
|
|
).create(Object.prototype);
|
|
|
|
assert.equal(Object.getPrototypeOf(o1), Object.prototype, "o1 prototype");
|
|
assert.equal(1, o1.a, "o1.a");
|
|
assert.equal(1, o1.b(), "o1.b()");
|
|
assert.equal(Object.keys(o1).length, 1, "Object.keys(o1).length === 2");
|
|
};
|
|
|
|
exports["test create with Array.prototype"] = function(assert) {
|
|
var o2 = Trait.compose({}, {}).create(Array.prototype);
|
|
assert.equal(Object.getPrototypeOf(o2), Array.prototype, "o2 prototype");
|
|
};
|
|
|
|
exports["test exception for incomplete required properties"] = function(assert) {
|
|
assert.throws(function() {
|
|
Trait({ foo: Trait.required }).create(Object.prototype)
|
|
}, /Missing required property: `foo`/, "required prop error");
|
|
}
|
|
|
|
exports["test exception for unresolved conflicts"] = function(assert) {
|
|
assert.throws(function() {
|
|
Trait(Trait({ a: 0 }), Trait({ a: 1 })).create({})
|
|
}, /Remaining conflicting property: `a`/, "conflicting prop error");
|
|
}
|
|
|
|
exports["test conflicting properties are present"] = function(assert) {
|
|
var o5 = Object.create(Object.prototype, Trait.compose(
|
|
{ a: { value: 0 } },
|
|
{ a: { value: 1 } }
|
|
));
|
|
|
|
assert.ok("a" in o5, "conflicting property present");
|
|
assert.throws(function() {
|
|
o5.a
|
|
}, /Remaining conflicting property: `a`/, "conflicting prop access error");
|
|
};
|
|
|
|
exports["test diamond with conflicts"] = function(assert) {
|
|
function makeT1(x) {
|
|
return {
|
|
m: {
|
|
value: function() {
|
|
return x
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
function makeT2(x) {
|
|
return Trait.compose(
|
|
Trait({ t2: "foo" }),
|
|
makeT1(x)
|
|
);
|
|
};
|
|
|
|
function makeT3(x) {
|
|
return Trait.compose(
|
|
{
|
|
t3: { value: "bar" }
|
|
},
|
|
makeT1(x)
|
|
);
|
|
};
|
|
|
|
var T4 = Trait.compose(makeT2(5), makeT3(5));
|
|
|
|
assert.throws(function() {
|
|
T4.create(Object.prototype);
|
|
}, /Remaining conflicting property: `m`/, "diamond prop conflict");
|
|
};
|
|
|
|
exports["test providing requirements through proto"] = function(assert) {
|
|
var t = Trait.compose(
|
|
{},
|
|
{ required: { required: true } }
|
|
).create({ required: "test" });
|
|
|
|
assert.equal(t.required, "test", "property from proto is inherited");
|
|
};
|
|
|
|
if (module == require.main)
|
|
require("test").run(exports);
|