Patches for dojo/aspect #2

Closed
wants to merge 3 commits into
from
View
@@ -27,18 +27,22 @@ define([], function(){
// create the remove handler
signal = {
remove: function(){
- var previous = signal.previous;
- var next = signal.next;
- if(!next && !previous){
- delete dispatcher[type];
- }else{
- if(previous){
- previous.next = next;
+ if(this.advice){
+ // remove the advice to signal that this signal has been removed
+ this.advice = null;
+ var previous = signal.previous;
+ var next = signal.next;
+ if(!next && !previous){
+ delete dispatcher[type];
}else{
- dispatcher[type] = next;
- }
- if(next){
- next.previous = previous;
+ if(previous){
+ previous.next = next;
+ }else{
+ dispatcher[type] = next;
+ }
+ if(next){
+ next.previous = previous;
+ }
}
}
},
@@ -50,11 +54,8 @@ define([], function(){
if(previous && !around){
if(type == "after"){
// add the listener to the end of the list
- var next = previous;
- while(next){
- previous = next;
- next = next.next;
- }
+ // note that we had to change this loop a little bit to workaround a bizarre IE10 JIT bug
+ while(previous.next && (previous = previous.next)){}
previous.next = signal;
signal.previous = previous;
}else if(type == "before"){
@@ -80,7 +81,9 @@ define([], function(){
var args = arguments;
var before = dispatcher.before;
while(before){
- args = before.advice.apply(this, args) || args;
+ if(before.advice){
+ args = before.advice.apply(this, args) || args;
+ }
before = before.next;
}
// around advice
View
@@ -82,6 +82,17 @@ doh.register("tests.aspect",
}, true);
t.t(obj.method() === false);
},
+ function afterMultiple(t){
+ var order = [];
+ obj = {
+ foo: function(){}
+ };
+ aspect.after(obj, "foo", function(){order.push(1)});
+ aspect.after(obj, "foo", function(){order.push(2)});
+ aspect.after(obj, "foo", function(){order.push(3)});
+ obj.foo();
+ t.is([1,2,3], order);
+ },
function around(t){
var order = [];
var obj = {
@@ -105,6 +116,36 @@ doh.register("tests.aspect",
obj.method(4);
t.is(order, [0,1,2,3,4,5,6]);
},
+ function multipleRemove(t){
+ var foo = {bar: function(){}};
+ var order = [];
+ var signal1 = aspect.after(foo, "bar", function() {
+ order.push(1);
+ });
+
+ var signal2 = aspect.after(foo, "bar", function() {
+ order.push(2);
+ });
+
+ var signal3 = aspect.after(foo, "bar", function() {
+ order.push(3);
+ });
+
+ // This should execute all 3 callbacks
+ foo.bar();
+
+ signal2.remove();
+ signal3.remove();
+
+ // Ideally signal2 should not be removed again, but can happen if the app
+ // fails to clear its state.
+ signal2.remove();
+
+ // This should execute only the first callback, but notice that the third callback
+ // is executed as well
+ foo.bar();
+ t.is(order, [1,2,3,1]);
+ },
function delegation(t){
var order = [];
var proto = {