Comparing version 0.2.1 to 0.2.3
/* | ||
* See example/counting.html | ||
*/ | ||
Zone.countingZone = { | ||
'-onZoneCreated': function () { | ||
Zone.countingZone.counter += 1; | ||
// setTimeout | ||
'+enqueueTask': function () { | ||
this.data.count += 1; | ||
}, | ||
// fires when... | ||
// - clearTimeout | ||
// - setTimeout finishes | ||
'-dequeueTask': function () { | ||
this.data.count -= 1; | ||
}, | ||
'+afterTask': function () { | ||
Zone.countingZone.counter -= 1; | ||
if (Zone.countingZone.counter <= 0) { | ||
Zone.countingZone.counter = 0; | ||
this.onFlush(); | ||
if (this.data.count === 0 && !this.data.flushed) { | ||
this.data.flushed = true; | ||
this.run(this.onFlush); | ||
} | ||
}, | ||
'-run': function () { | ||
Zone.countingZone.counter = 0; | ||
}, | ||
counter: function () { | ||
return Zone.countingZone.counter; | ||
return this.data.count; | ||
}, | ||
data: { | ||
count: 0, | ||
flushed: false | ||
}, | ||
onFlush: function () {} | ||
}; |
@@ -9,3 +9,3 @@ // Karma configuration | ||
'*-zone.js', | ||
'test/*.spec.js' | ||
'test/**/*.spec.js' | ||
], | ||
@@ -12,0 +12,0 @@ |
@@ -11,9 +11,7 @@ /* | ||
Zone.Stacktrace.prototype.get = function () { | ||
var frames = this._e.stack.split('\n'); | ||
var markerIndex; | ||
for (var markerIndex = frames.length - 1; markerIndex >= 0; markerIndex -= 1) { | ||
if (frames[markerIndex].indexOf('marker@') === 0) { | ||
return frames.slice(markerIndex+1).join('\n'); | ||
} | ||
if (zone.stackFramesFilter) { | ||
return this._e.stack. | ||
split('\n'). | ||
filter(zone.stackFramesFilter). | ||
join('\n'); | ||
} | ||
@@ -50,4 +48,11 @@ return this._e.stack; | ||
getLongStacktrace: function (exception) { | ||
var trace = [exception.stack]; | ||
var trace = []; | ||
var zone = this; | ||
if (zone.stackFramesFilter) { | ||
trace.push(exception.stack.split('\n'). | ||
filter(zone.stackFramesFilter). | ||
join('\n')); | ||
} else { | ||
trace.push(exception.stack); | ||
} | ||
var now = Date.now(); | ||
@@ -64,2 +69,6 @@ while (zone && zone.constructedAtException) { | ||
stackFramesFilter: function (line) { | ||
return line.indexOf('zone.js') === -1; | ||
}, | ||
onError: function (exception) { | ||
@@ -66,0 +75,0 @@ var reporter = this.reporter || console.log.bind(console); |
{ | ||
"name": "zone.js", | ||
"version": "0.2.1", | ||
"version": "0.2.3", | ||
"description": "Zones for JavaScript", | ||
@@ -18,3 +18,3 @@ "main": "zone.js", | ||
"author": "Brian Ford", | ||
"license": "MIT", | ||
"license": "Apache 2.0", | ||
"bugs": { | ||
@@ -21,0 +21,0 @@ "url": "https://github.com/btford/zone.js/issues" |
@@ -63,2 +63,9 @@ # Zone.js | ||
## Usage | ||
To start using Zones, you need to include the `zone.js` script in this package onto | ||
your page. This script should appear in the `<head>` of your HTML file before any other | ||
scripts, including shims/polyfills. | ||
## Examples | ||
@@ -225,2 +232,12 @@ | ||
### `zone.enqueueTask` | ||
This hook is called when a function is registered with the VM. | ||
For instance `setTimeout` and `addEventListener`. | ||
### `zone.dequeueTask` | ||
This hook is called when a function is unregistered with the VM. | ||
For instance `clearTimeout` and `removeEventListener`. | ||
### `zone.setTimeout`, `zone.setInterval`, `zone.alert`, `zone.prompt` | ||
@@ -227,0 +244,0 @@ |
'use strict'; | ||
describe('Zone.countingZone', function () { | ||
var flushSpy = jasmine.createSpy('flush'), | ||
countingZone = zone.fork(Zone.countingZone).fork({ | ||
onFlush: flushSpy | ||
}); | ||
var flushSpy, countingZone; | ||
beforeEach(function () { | ||
jasmine.Clock.useMock(); | ||
flushSpy.reset(); | ||
flushSpy = jasmine.createSpy('flush'); | ||
countingZone = zone.fork(Zone.longStackTraceZone). | ||
fork(Zone.countingZone). | ||
fork({ | ||
onFlush: flushSpy | ||
}); | ||
}); | ||
it('should flush at the end of a run', function () { | ||
countingZone.run(function () {}); | ||
expect(flushSpy).toHaveBeenCalled(); | ||
countingZone.run(function () { | ||
expect(countingZone.counter()).toBe(0); | ||
}); | ||
expect(countingZone.counter()).toBe(0); | ||
expect(flushSpy.calls.length).toBe(1); | ||
}); | ||
it('should work', function () { | ||
it('should work with setTimeout', function () { | ||
var latch; | ||
runs(function () { | ||
countingZone.run(function () { | ||
setTimeout(function () { | ||
latch = true; | ||
}, 0); | ||
expect(countingZone.counter()).toBe(1); | ||
}); | ||
}); | ||
waitsFor(function () { | ||
return latch; | ||
}); | ||
runs(function () { | ||
expect(countingZone.counter()).toBe(0); | ||
}) | ||
}); | ||
it('should work with clearTimeout', function () { | ||
var latch = false; | ||
countingZone.run(function () { | ||
var id = setTimeout(function () { | ||
latch = true; | ||
}, 0); | ||
expect(countingZone.counter()).toBe(1); | ||
clearTimeout(id); | ||
expect(countingZone.counter()).toBe(0); | ||
}); | ||
}); | ||
setTimeout(function () {}, 0); | ||
it('should work with setInterval', function () { | ||
var latch = 0, id; | ||
runs(function () { | ||
countingZone.run(function () { | ||
id = setInterval(function () { | ||
latch += 1; | ||
}, 0); | ||
expect(countingZone.counter()).toBe(1); | ||
}); | ||
}); | ||
waitsFor(function () { | ||
return latch === 2; | ||
}, 100, 'latch to increment'); | ||
runs(function () { | ||
expect(countingZone.counter()).toBe(1); | ||
clearInterval(id); | ||
}); | ||
}); | ||
//jasmine.Clock.tick(0); | ||
it('should work with clearInterval', function () { | ||
var id; | ||
countingZone.run(function () { | ||
id = setInterval(function () { | ||
latch += 1; | ||
}, 0); | ||
expect(countingZone.counter()).toBe(1); | ||
clearInterval(id); | ||
expect(countingZone.counter()).toBe(0); | ||
}); | ||
}); | ||
//expect(countingZone.counter()).toBe(0); | ||
it('should work with addEventListener', function () { | ||
var elt = document.createElement('button'); | ||
var clicked = false; | ||
runs(function () { | ||
countingZone.run(main); | ||
}); | ||
//jasmine.Clock.tick(0); | ||
function main () { | ||
expect(countingZone.counter()).toBe(0); | ||
elt.addEventListener('click', onClick); | ||
expect(countingZone.counter()).toBe(1); | ||
elt.click(); | ||
function onClick () { | ||
expect(countingZone.counter()).toBe(1); | ||
elt.removeEventListener('click', onClick); | ||
expect(countingZone.counter()).toBe(0); | ||
clicked = true; | ||
} | ||
expect(countingZone.counter()).toBe(0); | ||
} | ||
waitsFor(function () { | ||
return clicked; | ||
}, 10, 'the thing'); | ||
runs(function () { | ||
expect(flushSpy.calls.length).toBe(1); | ||
}); | ||
}); | ||
}); |
'use strict'; | ||
describe('Zone.patch', function () { | ||
describe('longStackTraceZone', function () { | ||
var log; | ||
@@ -32,2 +31,20 @@ | ||
}); | ||
it('should filter based on stackFramesFilter', function () { | ||
lstz.fork({ | ||
stackFramesFilter: function (line) { | ||
return line.indexOf('jasmine.js') === -1; | ||
} | ||
}).run(function () { | ||
setTimeout(function () { | ||
setTimeout(function () { | ||
throw new Error('hello'); | ||
}, 0); | ||
}, 0); | ||
}); | ||
jasmine.Clock.tick(0); | ||
expect(log[1]).not.toContain('jasmine.js'); | ||
}); | ||
}); |
'use strict'; | ||
describe('Zone', function () { | ||
describe('Zone.patch', function () { | ||
beforeEach(function () { | ||
@@ -10,447 +9,2 @@ zone.mark = 'root'; | ||
describe('setTimeout', function () { | ||
beforeEach(function () { | ||
jasmine.Clock.useMock(); | ||
}); | ||
it('should work with setTimeout', function () { | ||
var childZone = window.zone.fork({ | ||
mark: 'child' | ||
}); | ||
expect(zone.mark).toEqual('root'); | ||
childZone.run(function() { | ||
expect(zone.mark).toEqual('child'); | ||
expect(zone).toEqual(childZone); | ||
window.setTimeout(function() { | ||
// creates implied zone in all callbacks. | ||
expect(zone).not.toEqual(childZone); | ||
expect(zone.parent).toEqual(childZone); | ||
expect(zone.mark).toEqual('child'); // proto inherited | ||
}, 0); | ||
expect(zone.mark).toEqual('child'); | ||
}); | ||
expect(zone.mark).toEqual('root'); | ||
}); | ||
it('should allow canceling of fns registered with setTimeout', function () { | ||
var spy = jasmine.createSpy(); | ||
var cancelId = window.setTimeout(spy, 0); | ||
window.clearTimeout(cancelId); | ||
jasmine.Clock.tick(1); | ||
expect(spy).not.toHaveBeenCalled(); | ||
}); | ||
}); | ||
describe('setInterval', function () { | ||
beforeEach(function () { | ||
jasmine.Clock.useMock(); | ||
}); | ||
it('should work with setInterval', function () { | ||
var childZone = window.zone.fork({ | ||
mark: 'child' | ||
}); | ||
expect(zone.mark).toEqual('root'); | ||
childZone.run(function() { | ||
expect(zone.mark).toEqual('child'); | ||
expect(zone).toEqual(childZone); | ||
var cancelId = window.setInterval(function() { | ||
// creates implied zone in all callbacks. | ||
expect(zone).not.toEqual(childZone); | ||
expect(zone.parent).toEqual(childZone); | ||
expect(zone.mark).toEqual('child'); // proto inherited | ||
}, 10); | ||
jasmine.Clock.tick(11); | ||
expect(zone.mark).toEqual('child'); | ||
clearInterval(cancelId); | ||
}); | ||
expect(zone.mark).toEqual('root'); | ||
}); | ||
}); | ||
describe('requestAnimationFrame', function () { | ||
var flag, hasParent, skip = false; | ||
it('should work', function (done) { | ||
if (!window.requestAnimationFrame) { | ||
console.log('WARNING: skipping requestAnimationFrame test (missing this API)'); | ||
return; | ||
} | ||
// Some browsers (especially Safari) do not fire requestAnimationFrame | ||
// if they are offscreen. We can disable this test for those browsers and | ||
// assume the patch works if setTimeout works, since they are mechanically | ||
// the same | ||
runs(function() { | ||
flag = false; | ||
window.requestAnimationFrame(function () { | ||
flag = true; | ||
}); | ||
setTimeout(function () { | ||
skip = true; | ||
flag = true; | ||
console.log('WARNING: skipping requestAnimationFrame test (not firing rAF)'); | ||
}, 50); | ||
}); | ||
waitsFor(function() { | ||
return flag; | ||
}, "requestAnimationFrame to run", 100); | ||
runs(function() { | ||
flag = false; | ||
hasParent = false; | ||
window.requestAnimationFrame(function () { | ||
hasParent = !!window.zone.parent; | ||
flag = true; | ||
}); | ||
}); | ||
waitsFor(function() { | ||
return flag || skip; | ||
}, "requestAnimationFrame to run", 100); | ||
runs(function() { | ||
expect(hasParent || skip).toBe(true); | ||
}); | ||
}); | ||
}); | ||
describe('webkitRequestAnimationFrame', function () { | ||
var flag, hasParent, skip = false; | ||
it('should work', function (done) { | ||
if (!window.webkitRequestAnimationFrame) { | ||
console.log('WARNING: skipping webkitRequestAnimationFrame test (missing this API)'); | ||
return; | ||
} | ||
// Some browsers (especially Safari) do not fire webkitRequestAnimationFrame | ||
// if they are offscreen. We can disable this test for those browsers and | ||
// assume the patch works if setTimeout works, since they are mechanically | ||
// the same | ||
runs(function() { | ||
flag = false; | ||
window.webkitRequestAnimationFrame(function () { | ||
flag = true; | ||
}); | ||
setTimeout(function () { | ||
skip = true; | ||
flag = true; | ||
console.log('WARNING: skipping webkitRequestAnimationFrame test (not firing rAF)'); | ||
}, 50); | ||
}); | ||
waitsFor(function() { | ||
return flag; | ||
}, 'webkitRequestAnimationFrame to run', 100); | ||
runs(function() { | ||
flag = false; | ||
hasParent = false; | ||
window.webkitRequestAnimationFrame(function () { | ||
hasParent = !!window.zone.parent; | ||
flag = true; | ||
}); | ||
}); | ||
waitsFor(function() { | ||
return flag || skip; | ||
}, 'webkitRequestAnimationFrame to run', 100); | ||
runs(function() { | ||
expect(hasParent || skip).toBe(true); | ||
}); | ||
}); | ||
}); | ||
describe('Promise', function () { | ||
var flag, hasParent; | ||
beforeEach(function () { | ||
jasmine.Clock.useMock(); | ||
flag = false; | ||
hasParent = false; | ||
}); | ||
it('should work with .then', function () { | ||
if (!window.Promise) { | ||
console.log('WARNING: skipping Promise test (missing this API)'); | ||
return; | ||
} | ||
runs(function () { | ||
new Promise(function (resolve) { | ||
setTimeout(resolve, 0); | ||
}).then(function () { | ||
hasParent = !!window.zone.parent; | ||
flag = true; | ||
}); | ||
jasmine.Clock.tick(1); | ||
}); | ||
waitsFor(function() { | ||
return flag; | ||
}, 'promise to resolve', 100); | ||
runs(function() { | ||
expect(hasParent).toBe(true); | ||
}); | ||
}); | ||
it('should work with .catch', function () { | ||
if (!window.Promise) { | ||
return; | ||
} | ||
runs(function() { | ||
new Promise(function (resolve, reject) { | ||
setTimeout(reject, 0); | ||
}).catch(function () { | ||
hasParent = !!window.zone.parent; | ||
flag = true; | ||
}); | ||
jasmine.Clock.tick(1); | ||
}); | ||
waitsFor(function() { | ||
return flag; | ||
}, "promise to reject", 100); | ||
runs(function() { | ||
expect(hasParent).toBe(true); | ||
}); | ||
}); | ||
}); | ||
describe('element', function () { | ||
var button; | ||
beforeEach(function () { | ||
button = document.createElement('button'); | ||
document.body.appendChild(button); | ||
}); | ||
afterEach(function () { | ||
document.body.removeChild(button); | ||
button.remove(); | ||
}); | ||
it('should work with addEventListener', function () { | ||
var zoneHasParent; | ||
button.addEventListener('click', function () { | ||
zoneHasParent = !!window.zone.parent; | ||
}); | ||
button.click(); | ||
expect(zoneHasParent).toEqual(true); | ||
}); | ||
it('should respect removeEventListener', function () { | ||
var log = ''; | ||
var logOnClick = function logOnClick () { | ||
log += 'a'; | ||
}; | ||
button.addEventListener('click', logOnClick); | ||
button.click(); | ||
expect(log).toEqual('a'); | ||
button.removeEventListener('click', logOnClick); | ||
button.click(); | ||
expect(log).toEqual('a'); | ||
}); | ||
it('should work with onclick', function () { | ||
var zoneHasParent; | ||
button.onclick = function () { | ||
zoneHasParent = !!window.zone.parent; | ||
}; | ||
button.click(); | ||
expect(zoneHasParent).toEqual(true); | ||
}); | ||
it('should only allow one onclick handler', function () { | ||
var log = ''; | ||
button.onclick = function () { | ||
log += 'a'; | ||
}; | ||
button.onclick = function () { | ||
log += 'b'; | ||
}; | ||
button.click(); | ||
expect(log).toEqual('b'); | ||
}); | ||
it('should handle removing onclick', function () { | ||
var log = ''; | ||
button.onclick = function () { | ||
log += 'a'; | ||
}; | ||
button.onclick = null; | ||
button.click(); | ||
expect(log).toEqual(''); | ||
}); | ||
}); | ||
describe('MutationObserver', function () { | ||
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 () { | ||
var ob = new MutationObserver(function () { | ||
hasParent = !!window.zone.parent; | ||
flag = true; | ||
}); | ||
ob.observe(elt, { | ||
childList: true | ||
}); | ||
elt.innerHTML = '<p>hey</p>'; | ||
}); | ||
waitsFor(function() { | ||
return flag; | ||
}, 'mutation observer to fire', 100); | ||
runs(function() { | ||
expect(hasParent).toBe(true); | ||
}); | ||
}); | ||
}); | ||
describe('WebKitMutationObserver', function () { | ||
it('should work', function () { | ||
if (!window.WebKitMutationObserver) { | ||
console.log('WARNING: skipping WebKitMutationObserver test (missing this API)'); | ||
return; | ||
} | ||
var flag = false, | ||
elt = document.createElement('div'), | ||
hasParent; | ||
runs(function () { | ||
var ob = new WebKitMutationObserver(function () { | ||
hasParent = !!window.zone.parent; | ||
flag = true; | ||
}); | ||
ob.observe(elt, { | ||
childList: true | ||
}); | ||
elt.innerHTML = '<p>hey</p>'; | ||
}); | ||
waitsFor(function() { | ||
return flag; | ||
}, 'mutation observer to fire', 100); | ||
runs(function() { | ||
expect(hasParent).toBe(true); | ||
}); | ||
}); | ||
}); | ||
describe('XMLHttpRequest', function () { | ||
it('should work with onreadystatechange', function () { | ||
var flag = false, | ||
hasParent; | ||
runs(function () { | ||
var req = new XMLHttpRequest(); | ||
req.onreadystatechange = function () { | ||
hasParent = !!window.zone.parent; | ||
flag = true; | ||
}; | ||
req.open('get', '/', true); | ||
req.send(); | ||
}); | ||
waitsFor(function() { | ||
return flag; | ||
}, 'HTTP request to resolve', 100); | ||
runs(function() { | ||
expect(hasParent).toBe(true); | ||
}); | ||
}); | ||
it('should work with onprogress', function () { | ||
var flag = false, | ||
hasParent; | ||
runs(function () { | ||
var req = new XMLHttpRequest(); | ||
req.onprogress = function () { | ||
hasParent = !!window.zone.parent; | ||
flag = true; | ||
}; | ||
req.open('get', '/', true); | ||
req.send(); | ||
}); | ||
waitsFor(function() { | ||
return flag; | ||
}, 'HTTP request to resolve', 100); | ||
runs(function() { | ||
expect(hasParent).toBe(true); | ||
}); | ||
}); | ||
it('should preserve other setters', function () { | ||
var req = new XMLHttpRequest(); | ||
req.open('get', '/', true); | ||
req.send(); | ||
req.responseType = 'document'; | ||
expect(req.responseType).toBe('document'); | ||
}); | ||
}); | ||
describe('hooks', function () { | ||
@@ -578,2 +132,13 @@ | ||
describe('fork', function () { | ||
it('should fork deep copy', function () { | ||
var protoZone = { too: { deep: true } }, | ||
a = zone.fork(protoZone), | ||
b = zone.fork(protoZone); | ||
expect(a.too).not.toBe(b.too); | ||
expect(a.too).toEqual(b.too); | ||
}); | ||
}); | ||
}); | ||
@@ -580,0 +145,0 @@ |
209
zone.js
@@ -42,3 +42,5 @@ 'use strict'; | ||
} else { | ||
zone[property] = data[property]; | ||
zone[property] = (typeof data[property] === 'object') ? | ||
JSON.parse(JSON.stringify(data[property])) : | ||
data[property]; | ||
} | ||
@@ -59,3 +61,4 @@ }); | ||
bind: function (fn) { | ||
bind: function (fn, skipEnqueue) { | ||
skipEnqueue || this.enqueueTask(fn); | ||
var zone = this.fork(); | ||
@@ -67,2 +70,10 @@ return function zoneBoundFn() { | ||
bindOnce: function (fn) { | ||
return this.bind(function () { | ||
var result = fn.apply(this, arguments); | ||
zone.dequeueTask(fn); | ||
return result; | ||
}); | ||
}, | ||
run: function run (fn, applyTo, applyWith) { | ||
@@ -94,14 +105,83 @@ applyWith = applyWith || []; | ||
onZoneCreated: function () {}, | ||
afterTask: function () {} | ||
afterTask: function () {}, | ||
enqueueTask: function () {}, | ||
dequeueTask: function () {} | ||
}; | ||
Zone.patchFn = function (obj, fnNames) { | ||
Zone.patchSetClearFn = function (obj, fnNames) { | ||
fnNames.map(function (name) { | ||
return name[0].toUpperCase() + name.substr(1); | ||
}). | ||
forEach(function (name) { | ||
var setName = 'set' + name; | ||
var clearName = 'clear' + name; | ||
var delegate = obj[setName]; | ||
if (delegate) { | ||
var ids = {}; | ||
if (setName === 'setInterval') { | ||
zone[setName] = function (fn) { | ||
var id; | ||
arguments[0] = function () { | ||
delete ids[id]; | ||
return fn.apply(this, arguments); | ||
}; | ||
var args = Zone.bindArguments(arguments); | ||
id = delegate.apply(obj, args); | ||
ids[id] = true; | ||
return id; | ||
}; | ||
} else { | ||
zone[setName] = function (fn) { | ||
var id; | ||
arguments[0] = function () { | ||
delete ids[id]; | ||
return fn.apply(this, arguments); | ||
}; | ||
var args = Zone.bindArgumentsOnce(arguments); | ||
id = delegate.apply(obj, args); | ||
ids[id] = true; | ||
return id; | ||
}; | ||
} | ||
obj[setName] = function () { | ||
return zone[setName].apply(this, arguments); | ||
}; | ||
var clearDelegate = obj[clearName]; | ||
zone[clearName] = function (id) { | ||
if (ids[id]) { | ||
delete ids[id]; | ||
zone.dequeueTask(); | ||
} | ||
return clearDelegate.apply(this, arguments); | ||
}; | ||
obj[clearName] = function () { | ||
return zone[clearName].apply(this, arguments); | ||
}; | ||
} | ||
}); | ||
}; | ||
Zone.patchSetFn = function (obj, fnNames) { | ||
fnNames.forEach(function (name) { | ||
var delegate = obj[name]; | ||
if (delegate) { | ||
zone[name] = function () { | ||
return delegate.apply(obj, Zone.bindArguments(arguments)); | ||
zone[name] = function (fn) { | ||
arguments[0] = function () { | ||
return fn.apply(this, arguments); | ||
}; | ||
var args = Zone.bindArgumentsOnce(arguments); | ||
return delegate.apply(obj, args); | ||
}; | ||
obj[name] = function marker () { | ||
obj[name] = function () { | ||
return zone[name].apply(this, arguments); | ||
@@ -133,2 +213,12 @@ }; | ||
Zone.bindArgumentsOnce = function (args) { | ||
for (var i = args.length - 1; i >= 0; i--) { | ||
if (typeof args[i] === 'function') { | ||
args[i] = zone.bindOnce(args[i]); | ||
} | ||
} | ||
return args; | ||
}; | ||
Zone.patchableFn = function (obj, fnNames) { | ||
@@ -212,3 +302,5 @@ fnNames.forEach(function (name) { | ||
arguments[1] = arguments[1]._bound || arguments[1]; | ||
return removeDelegate.apply(this, arguments); | ||
var result = removeDelegate.apply(this, arguments); | ||
zone.dequeueTask(fn); | ||
return result; | ||
}; | ||
@@ -218,8 +310,13 @@ }; | ||
Zone.patch = function patch () { | ||
Zone.patchFn(window, [ | ||
'setTimeout', | ||
'setInterval', | ||
Zone.patchSetClearFn(window, [ | ||
'timeout', | ||
'interval', | ||
'immediate' | ||
]); | ||
Zone.patchSetFn(window, [ | ||
'requestAnimationFrame', | ||
'webkitRequestAnimationFrame' | ||
]); | ||
Zone.patchableFn(window, ['alert', 'prompt']); | ||
@@ -277,4 +374,5 @@ | ||
} | ||
Zone.patchClass('MutationObserver'); | ||
Zone.patchClass('WebKitMutationObserver'); | ||
Zone.patchMutationObserverClass('MutationObserver'); | ||
Zone.patchMutationObserverClass('WebKitMutationObserver'); | ||
Zone.patchRegisterElement(); | ||
}; | ||
@@ -299,5 +397,3 @@ | ||
Zone.patchViaPropertyDescriptor = function () { | ||
Zone.patchProperties(HTMLElement.prototype, Zone.eventNames.map(function (property) { | ||
return 'on' + property; | ||
})); | ||
Zone.patchProperties(HTMLElement.prototype, Zone.onEventNames); | ||
Zone.patchProperties(XMLHttpRequest.prototype); | ||
@@ -326,3 +422,3 @@ }; | ||
// TODO: wrap some native API | ||
// wrap some native API on `window` | ||
Zone.patchClass = function (className) { | ||
@@ -372,3 +468,82 @@ var OriginalClass = window[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(); | ||
} | ||
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.patchRegisterElement = function () { | ||
if (!('registerElement' in document)) { | ||
return; | ||
} | ||
var _registerElement = document.registerElement; | ||
var callbacks = [ | ||
'createdCallback', | ||
'attachedCallback', | ||
'detachedCallback', | ||
'attributeChangedCallback' | ||
]; | ||
document.registerElement = function (name, opts) { | ||
callbacks.forEach(function (callback) { | ||
if (opts.prototype[callback]) { | ||
opts.prototype[callback] = zone.bind(opts.prototype[callback]); | ||
} | ||
}); | ||
return _registerElement.apply(document, [name, opts]); | ||
}; | ||
} | ||
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; | ||
}); | ||
@@ -375,0 +550,0 @@ Zone.init = function init () { |
Sorry, the diff of this file is not supported yet
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
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
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
184892
34
0
1603
265