Permalink
Browse files

Prevent multiple remove() calls on an aspect signal from corrupting t…

…he aspect chain, fixes #16513 !strict
  • Loading branch information...
1 parent 6a7eff0 commit 553c33812c0684514110fe34547cb0e709696e8d @kriszyp kriszyp committed with novemberborn Dec 27, 2012
Showing with 56 additions and 11 deletions.
  1. +15 −11 aspect.js
  2. +41 −0 tests/aspect.js
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;
+ }
}
}
},
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 = {

0 comments on commit 553c338

Please sign in to comment.