Comparing version 0.1.0 to 0.1.2
{ | ||
"name": "compose", | ||
"version": "0.1.0", | ||
"version": "0.1.2", | ||
"author": "Kris Zyp", | ||
@@ -21,11 +21,12 @@ "description": "Fast and light object composition based on mixins and traits", | ||
"dependencies": { | ||
"patr": "0.2.4" | ||
"patr": "0.2.5" | ||
}, | ||
"directories": { | ||
"lib": "./lib" | ||
"lib": "." | ||
}, | ||
"main": "./lib/compose", | ||
"main": "./compose", | ||
"mappings":{ | ||
"patr": "http://github.com/kriszyp/patr/zipball/v0.2.4" | ||
} | ||
"patr": "http://github.com/kriszyp/patr/zipball/v0.2.5" | ||
}, | ||
"icon": "http://icons.iconarchive.com/icons/kawsone/teneo/64/BiiBall-icon.png" | ||
} |
# ComposeJS | ||
ComposeJS is robust object composition built on native JavaScript mechanisms. | ||
ComposeJS is lightweight (4K minified, 1.3K gzipped) JavaScript module based on the | ||
ComposeJS is lightweight (3K minified, 1K gzipped) JavaScript module based on the | ||
philosophy that JavaScript's | ||
@@ -211,3 +211,3 @@ powerful composition mechanisms, including prototype inheritance, closures, and object | ||
than creating a constructor, it directly creates an instance object. Calling the constructor | ||
returned from Compose with no argumetns and calling Compose.create act approximately | ||
returned from Compose with no arguments and calling Compose.create act approximately | ||
the same action, i.e. Compose(...)() acts the same as Compose.create(...). The main | ||
@@ -250,2 +250,17 @@ difference is that Compose.create is optimized for instance creation and avoids | ||
##Constructor.extend | ||
Constructors created with Compose also include a "static" extend method that can be | ||
used for convenience in creating subclasses. The extend method behaves the same | ||
as Compose with the target class being the first parameter: | ||
<pre> | ||
MyClass = Compose(...); | ||
SubClass = MyClass.extend({ | ||
subMethod: function(){} | ||
}); | ||
// same as: | ||
SubClass = Compose(MyClass,{ | ||
subMethod: function(){} | ||
}); | ||
</pre> | ||
## Decorators | ||
@@ -288,3 +303,4 @@ Decorators provides a customized way to add properties/methods to target objects. | ||
inherited function. If nothing is returned, the original calling arguments are passed to | ||
the inherited function. | ||
the inherited function. If Compose.stop is returned, the inherited function will not be | ||
called. | ||
@@ -308,26 +324,2 @@ The around function allows one to closure around an overriden method to combine | ||
You can also apply aspects to existing instances. For example, we can add a listener | ||
for each time render is called on a widget instance: | ||
<pre> | ||
var widget = new Widget(node); | ||
Compose.after(widget, "render", function(){ | ||
console.log("render called"); | ||
}); | ||
</pre> | ||
You can also use the aspect functions as methods that are applied to their instances. | ||
For example, we could add the after() function as an on() method: | ||
<pre> | ||
var after = Compose.after; | ||
WidgetEventEmitter = Compose(Widget, { | ||
on: after | ||
}); | ||
var widget = new WidgetEventEmitter(node); | ||
widget.on("render", function(){ | ||
console.log("render called"); | ||
}); | ||
</pre> | ||
All the aspect functions (before, after, and around) can be applied to existing instances or used as methods as demonstrated above. | ||
### Composition Control: Method Aliasing and Exclusion | ||
@@ -334,0 +326,0 @@ One of the key capabilities of traits-style composition is control of which method to |
var assert = require("assert"), | ||
Compose = require("../lib/compose"), | ||
Compose = require("../compose"), | ||
required = Compose.required, | ||
@@ -36,3 +36,3 @@ around = Compose.around, | ||
}; | ||
exports.testInheritance= function() { | ||
exports.testInheritance = function() { | ||
MessageWidget = Compose(Widget, { | ||
@@ -49,2 +49,14 @@ message: "Hello, World", | ||
}; | ||
exports.testInheritanceViaExtend = function() { | ||
MessageWidget = Widget.extend({ | ||
message: "Hello, World", | ||
render: function(){ | ||
this.node.innerHTML = "<div>" + this.message + "</div>"; | ||
} | ||
}); | ||
var node = {}; | ||
var widget = new MessageWidget(node); | ||
widget.render(); | ||
assert.equal(node.innerHTML, "<div>Hello, World</div>"); | ||
}; | ||
exports.testInheritance2 = function() { | ||
@@ -245,3 +257,52 @@ SpanishWidget = Compose(MessageWidget, { | ||
assert.deepEqual(order, [1,2,3,4,5,6]); | ||
}; | ||
exports.testExtendError = function(){ | ||
var CustomError = Compose(Error, { | ||
name: "CustomError" | ||
}); | ||
var error = new CustomError("test"); | ||
assert.equal(error.name, "CustomError"); | ||
assert.equal(error.toString(), "CustomError: test"); | ||
assert.equal(error instanceof CustomError, true); | ||
assert.equal(error instanceof Error, true); | ||
} | ||
exports.testDiamond = function(){ | ||
var baseCallCount = 0, sub1CallCount = 0, sub2CallCount = 0, fooCallCount = 0, fooSub1Count = 0, fooSub2Count = 0; | ||
var Base = Compose(function(){ | ||
baseCallCount++; | ||
}, { | ||
foo: function(){ | ||
fooCallCount++; | ||
} | ||
}); | ||
var Sub1 = Compose(Base, function(){sub1CallCount++;}, { | ||
foo: Compose.after(function(){ | ||
fooSub1Count++; | ||
}) | ||
}); | ||
var Sub2 = Compose(Base, function(){sub2CallCount++;}, { | ||
foo: Compose.after(function(){ | ||
fooSub2Count++; | ||
}) | ||
}); | ||
var Combined = Sub1.extend(Sub2); | ||
var combined = new Combined; | ||
assert.equal(baseCallCount, 1); | ||
assert.equal(sub1CallCount, 1); | ||
assert.equal(sub2CallCount, 1); | ||
combined.foo(); | ||
assert.equal(fooCallCount, 1); | ||
//assert.equal(fooSub1Count, 1); // TODO: Should this be 1? | ||
assert.equal(fooSub2Count, 1); | ||
} | ||
exports.testNull = function() { | ||
var errored; | ||
try{ | ||
Compose(null, {}); | ||
}catch(e){ | ||
errored = true; | ||
} | ||
assert.equal(errored, true); | ||
} | ||
exports.testAdvice = function() { | ||
@@ -254,26 +315,44 @@ var order = []; | ||
}, | ||
on: Compose.after | ||
}; | ||
Compose.around(obj, "foo", function(base){ | ||
return function(){ | ||
order.push(2); | ||
try{ | ||
return base.apply(this, arguments); | ||
}finally{ | ||
order.push(4); | ||
Advised = Compose(obj, { | ||
"foo": Compose.around(function(base){ | ||
return function(){ | ||
order.push(2); | ||
try{ | ||
return base.apply(this, arguments); | ||
}finally{ | ||
order.push(4); | ||
} | ||
} | ||
} | ||
}) | ||
}); | ||
obj.on("foo", function(){ | ||
order.push(5); | ||
Advised = Compose(Advised, { | ||
"foo": Compose.after(function(){ | ||
order.push(5); | ||
}) | ||
}); | ||
Compose.before(obj, "foo", function(value){ | ||
order.push(value); | ||
return [3]; | ||
Advised = Compose(Advised, { | ||
"foo": Compose.before(function(value){ | ||
order.push(value); | ||
return [3]; | ||
}) | ||
}); | ||
obj = new Advised(); | ||
order.push(obj.foo(1)); | ||
assert.deepEqual(order, [1,2,3,4,5,6]); | ||
order = []; | ||
Advised = Compose(Advised, { | ||
"foo": Compose.before(function(value){ | ||
order.push(0); | ||
return Compose.stop; | ||
}) | ||
}); | ||
obj = new Advised(); | ||
obj.foo(1); | ||
assert.deepEqual(order, [0]); | ||
}; | ||
if (require.main === module) | ||
require("patr/runner").run(exports); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
33694
637
400
1
+ Addedpatr@0.2.5(transitive)
+ Addedpromised-io@0.2.3(transitive)
- Removedpatr@0.2.4(transitive)
- Removedpromised-io@0.2.2(transitive)
Updatedpatr@0.2.5