Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
fix: support MutationObserver.disconnect
Browse files Browse the repository at this point in the history
  • Loading branch information
btford committed May 8, 2014
1 parent 93c1468 commit ad711b8
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 5 deletions.
77 changes: 76 additions & 1 deletion test/patch/MutationObserver.spec.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
'use strict';

describe('MutationObserver', function () {
var elt;

beforeEach(function () {
elt = document.createElement('div');
});

it('should work', function () {
if (!window.MutationObserver) {
console.log('WARNING: skipping MutationObserver test (missing this API)');
return;
}

var flag = false,
elt = document.createElement('div'),
hasParent;

runs(function () {
Expand All @@ -33,6 +38,76 @@ describe('MutationObserver', function () {
});

});

it('should dequeue upon disconnect', function () {
if (!window.MutationObserver) {
console.log('WARNING: skipping MutationObserver test (missing this API)');
return;
}

var flag = false,
childZone = zone.fork({
dequeueTask: function () {
flag = true;
}
});

childZone.run(function () {
var ob = new MutationObserver(function () {});
ob.observe(elt, {
childList: true
});
ob.disconnect();
expect(flag).toBe(true);
});
});

it('should enqueue once upon observation', function () {
if (!window.MutationObserver) {
console.log('WARNING: skipping MutationObserver test (missing this API)');
return;
}

var count = 0,
childZone = zone.fork({
enqueueTask: function () {
count += 1;
}
});

childZone.run(function () {
var ob = new MutationObserver(function () {});
expect(count).toBe(0);

ob.observe(elt, { childList: true });
expect(count).toBe(1);

ob.observe(elt, { childList: true });
expect(count).toBe(1);
});
});

it('should only dequeue upon disconnect if something is observed', function () {
if (!window.MutationObserver) {
console.log('WARNING: skipping MutationObserver test (missing this API)');
return;
}

var flag = false,
elt = document.createElement('div'),
childZone = zone.fork({
dequeueTask: function () {
flag = true;
}
});

childZone.run(function () {
var ob = new MutationObserver(function () {});
ob.disconnect();
expect(flag).toBe(false);
});

});
});

describe('WebKitMutationObserver', function () {
Expand Down
64 changes: 60 additions & 4 deletions zone.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ Zone.prototype = {
return new Zone(this, locals);
},

bind: function (fn) {
this.enqueueTask(fn);
bind: function (fn, skipEnqueue) {
skipEnqueue || this.enqueueTask(fn);
var zone = this.fork();
return function zoneBoundFn() {
return zone.run(fn, this, arguments);
Expand Down Expand Up @@ -364,8 +364,8 @@ Zone.patch = function patch () {
'catch'
]);
}
Zone.patchClass('MutationObserver');
Zone.patchClass('WebKitMutationObserver');
Zone.patchMutationObserverClass('MutationObserver');
Zone.patchMutationObserverClass('WebKitMutationObserver');
};

//
Expand Down Expand Up @@ -454,6 +454,62 @@ Zone.patchClass = function (className) {
};
};

// wrap some native API on `window`
Zone.patchMutationObserverClass = function (className) {
var OriginalClass = window[className];
if (!OriginalClass) {
return;
}
window[className] = function (fn) {
this._o = new OriginalClass(zone.bind(fn, true));
};

var instance = new OriginalClass(function () {});

window[className].prototype.disconnect = function () {
var result = this._o.disconnect.apply(this._o, arguments);
this._active && zone.dequeueTask();
this._active = false;
return result;
};

window[className].prototype.observe = function () {
if (!this._active) {
zone.enqueueTask();
}
dump(this._active)
this._active = true;
return this._o.observe.apply(this._o, arguments);
};

var prop;
for (prop in instance) {
(function (prop) {
if (typeof window[className].prototype !== undefined) {
return;
}
if (typeof instance[prop] === 'function') {
window[className].prototype[prop] = function () {
return this._o[prop].apply(this._o, arguments);
};
} else {
Object.defineProperty(window[className].prototype, prop, {
set: function (fn) {
if (typeof fn === 'function') {
this._o[prop] = zone.bind(fn);
} else {
this._o[prop] = fn;
}
},
get: function () {
return this._o[prop];
}
});
}
}(prop));
}
};

Zone.eventNames = 'copy cut paste abort blur focus canplay canplaythrough change click contextmenu dblclick drag dragend dragenter dragleave dragover dragstart drop durationchange emptied ended input invalid keydown keypress keyup load loadeddata loadedmetadata loadstart mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup pause play playing progress ratechange reset scroll seeked seeking select show stalled submit suspend timeupdate volumechange waiting mozfullscreenchange mozfullscreenerror mozpointerlockchange mozpointerlockerror error'.split(' ');
Zone.onEventNames = Zone.eventNames.map(function (property) {
return 'on' + property;
Expand Down

0 comments on commit ad711b8

Please sign in to comment.