This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @license | |
* Copyright Google Inc. All Rights Reserved. | |
* | |
* Use of this source code is governed by an MIT-style license that can be | |
* found in the LICENSE file at https://angular.io/license | |
*/ | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory() : | |
typeof define === 'function' && define.amd ? define(factory) : | |
(factory()); | |
}(this, (function () { 'use strict'; | |
/** | |
* @license | |
* Copyright Google Inc. All Rights Reserved. | |
* | |
* Use of this source code is governed by an MIT-style license that can be | |
* found in the LICENSE file at https://angular.io/license | |
*/ | |
var Zone$1 = (function (global) { | |
var performance = global['performance']; | |
function mark(name) { | |
performance && performance['mark'] && performance['mark'](name); | |
} | |
function performanceMeasure(name, label) { | |
performance && performance['measure'] && performance['measure'](name, label); | |
} | |
mark('Zone'); | |
if (global['Zone']) { | |
// if global['Zone'] already exists (maybe zone.js was already loaded or | |
// some other lib also registered a global object named Zone), we may need | |
// to throw an error, but sometimes user may not want this error. | |
// For example, | |
// we have two web pages, page1 includes zone.js, page2 doesn't. | |
// and the 1st time user load page1 and page2, everything work fine, | |
// but when user load page2 again, error occurs because global['Zone'] already exists. | |
// so we add a flag to let user choose whether to throw this error or not. | |
// By default, if existing Zone is from zone.js, we will not throw the error. | |
if (global[('__zone_symbol__forceDuplicateZoneCheck')] === true || | |
typeof global['Zone'].__symbol__ !== 'function') { | |
throw new Error('Zone already loaded.'); | |
} | |
else { | |
return global['Zone']; | |
} | |
} | |
var Zone = /** @class */ (function () { | |
function Zone(parent, zoneSpec) { | |
this._parent = parent; | |
this._name = zoneSpec ? zoneSpec.name || 'unnamed' : '<root>'; | |
this._properties = zoneSpec && zoneSpec.properties || {}; | |
this._zoneDelegate = | |
new ZoneDelegate(this, this._parent && this._parent._zoneDelegate, zoneSpec); | |
} | |
Zone.assertZonePatched = function () { | |
if (global['Promise'] !== patches['ZoneAwarePromise']) { | |
throw new Error('Zone.js has detected that ZoneAwarePromise `(window|global).Promise` ' + | |
'has been overwritten.\n' + | |
'Most likely cause is that a Promise polyfill has been loaded ' + | |
'after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. ' + | |
'If you must load one, do so before loading zone.js.)'); | |
} | |
}; | |
Object.defineProperty(Zone, "root", { | |
get: function () { | |
var zone = Zone.current; | |
while (zone.parent) { | |
zone = zone.parent; | |
} | |
return zone; | |
}, | |
enumerable: true, | |
configurable: true | |
}); | |
Object.defineProperty(Zone, "current", { | |
get: function () { | |
return _currentZoneFrame.zone; | |
}, | |
enumerable: true, | |
configurable: true | |
}); | |
Object.defineProperty(Zone, "currentTask", { | |
get: function () { | |
return _currentTask; | |
}, | |
enumerable: true, | |
configurable: true | |
}); | |
Zone.__load_patch = function (name, fn) { | |
if (patches.hasOwnProperty(name)) { | |
throw Error('Already loaded patch: ' + name); | |
} | |
else if (!global['__Zone_disable_' + name]) { | |
var perfName = 'Zone:' + name; | |
mark(perfName); | |
patches[name] = fn(global, Zone, _api); | |
performanceMeasure(perfName, perfName); | |
} | |
}; | |
Object.defineProperty(Zone.prototype, "parent", { | |
get: function () { | |
return this._parent; | |
}, | |
enumerable: true, | |
configurable: true | |
}); | |
Object.defineProperty(Zone.prototype, "name", { | |
get: function () { | |
return this._name; | |
}, | |
enumerable: true, | |
configurable: true | |
}); | |
Zone.prototype.get = function (key) { | |
var zone = this.getZoneWith(key); | |
if (zone) | |
return zone._properties[key]; | |
}; | |
Zone.prototype.getZoneWith = function (key) { | |
var current = this; | |
while (current) { | |
if (current._properties.hasOwnProperty(key)) { | |
return current; | |
} | |
current = current._parent; | |
} | |
return null; | |
}; | |
Zone.prototype.fork = function (zoneSpec) { | |
if (!zoneSpec) | |
throw new Error('ZoneSpec required!'); | |
return this._zoneDelegate.fork(this, zoneSpec); | |
}; | |
Zone.prototype.wrap = function (callback, source) { | |
if (typeof callback !== 'function') { | |
throw new Error('Expecting function got: ' + callback); | |
} | |
var _callback = this._zoneDelegate.intercept(this, callback, source); | |
var zone = this; | |
return function () { | |
return zone.runGuarded(_callback, this, arguments, source); | |
}; | |
}; | |
Zone.prototype.run = function (callback, applyThis, applyArgs, source) { | |
_currentZoneFrame = { parent: _currentZoneFrame, zone: this }; | |
try { | |
return this._zoneDelegate.invoke(this, callback, applyThis, applyArgs, source); | |
} | |
finally { | |
_currentZoneFrame = _currentZoneFrame.parent; | |
} | |
}; | |
Zone.prototype.runGuarded = function (callback, applyThis, applyArgs, source) { | |
if (applyThis === void 0) { applyThis = null; } | |
_currentZoneFrame = { parent: _currentZoneFrame, zone: this }; | |
try { | |
try { | |
return this._zoneDelegate.invoke(this, callback, applyThis, applyArgs, source); | |
} | |
catch (error) { | |
if (this._zoneDelegate.handleError(this, error)) { | |
throw error; | |
} | |
} | |
} | |
finally { | |
_currentZoneFrame = _currentZoneFrame.parent; | |
} | |
}; | |
Zone.prototype.runTask = function (task, applyThis, applyArgs) { | |
if (task.zone != this) { | |
throw new Error('A task can only be run in the zone of creation! (Creation: ' + | |
(task.zone || NO_ZONE).name + '; Execution: ' + this.name + ')'); | |
} | |
// https://github.com/angular/zone.js/issues/778, sometimes eventTask | |
// will run in notScheduled(canceled) state, we should not try to | |
// run such kind of task but just return | |
if (task.state === notScheduled && task.type === eventTask) { | |
return; | |
} | |
var reEntryGuard = task.state != running; | |
reEntryGuard && task._transitionTo(running, scheduled); | |
task.runCount++; | |
var previousTask = _currentTask; | |
_currentTask = task; | |
_currentZoneFrame = { parent: _currentZoneFrame, zone: this }; | |
try { | |
if (task.type == macroTask && task.data && !task.data.isPeriodic) { | |
task.cancelFn = undefined; | |
} | |
try { | |
return this._zoneDelegate.invokeTask(this, task, applyThis, applyArgs); | |
} | |
catch (error) { | |
if (this._zoneDelegate.handleError(this, error)) { | |
throw error; | |
} | |
} | |
} | |
finally { | |
// if the task's state is notScheduled or unknown, then it has already been cancelled | |
// we should not reset the state to scheduled | |
if (task.state !== notScheduled && task.state !== unknown) { | |
if (task.type == eventTask || (task.data && task.data.isPeriodic)) { | |
reEntryGuard && task._transitionTo(scheduled, running); | |
} | |
else { | |
task.runCount = 0; | |
this._updateTaskCount(task, -1); | |
reEntryGuard && | |
task._transitionTo(notScheduled, running, notScheduled); | |
} | |
} | |
_currentZoneFrame = _currentZoneFrame.parent; | |
_currentTask = previousTask; | |
} | |
}; | |
Zone.prototype.scheduleTask = function (task) { | |
if (task.zone && task.zone !== this) { | |
// check if the task was rescheduled, the newZone | |
// should not be the children of the original zone | |
var newZone = this; | |
while (newZone) { | |
if (newZone === task.zone) { | |
throw Error("can not reschedule task to " + this.name + " which is descendants of the original zone " + task.zone.name); | |
} | |
newZone = newZone.parent; | |
} | |
} | |
task._transitionTo(scheduling, notScheduled); | |
var zoneDelegates = []; | |
task._zoneDelegates = zoneDelegates; | |
task._zone = this; | |
try { | |
task = this._zoneDelegate.scheduleTask(this, task); | |
} | |
catch (err) { | |
// should set task's state to unknown when scheduleTask throw error | |
// because the err may from reschedule, so the fromState maybe notScheduled | |
task._transitionTo(unknown, scheduling, notScheduled); | |
// TODO: @JiaLiPassion, should we check the result from handleError? | |
this._zoneDelegate.handleError(this, err); | |
throw err; | |
} | |
if (task._zoneDelegates === zoneDelegates) { | |
// we have to check because internally the delegate can reschedule the task. | |
this._updateTaskCount(task, 1); | |
} | |
if (task.state == scheduling) { | |
task._transitionTo(scheduled, scheduling); | |
} | |
return task; | |
}; | |
Zone.prototype.scheduleMicroTask = function (source, callback, data, customSchedule) { | |
return this.scheduleTask(new ZoneTask(microTask, source, callback, data, customSchedule, undefined)); | |
}; | |
Zone.prototype.scheduleMacroTask = function (source, callback, data, customSchedule, customCancel) { | |
return this.scheduleTask(new ZoneTask(macroTask, source, callback, data, customSchedule, customCancel)); | |
}; | |
Zone.prototype.scheduleEventTask = function (source, callback, data, customSchedule, customCancel) { | |
return this.scheduleTask(new ZoneTask(eventTask, source, callback, data, customSchedule, customCancel)); | |
}; | |
Zone.prototype.cancelTask = function (task) { | |
if (task.zone != this) | |
throw new Error('A task can only be cancelled in the zone of creation! (Creation: ' + | |
(task.zone || NO_ZONE).name + '; Execution: ' + this.name + ')'); | |
task._transitionTo(canceling, scheduled, running); | |
try { | |
this._zoneDelegate.cancelTask(this, task); | |
} | |
catch (err) { | |
// if error occurs when cancelTask, transit the state to unknown | |
task._transitionTo(unknown, canceling); | |
this._zoneDelegate.handleError(this, err); | |
throw err; | |
} | |
this._updateTaskCount(task, -1); | |
task._transitionTo(notScheduled, canceling); | |
task.runCount = 0; | |
return task; | |
}; | |
Zone.prototype._updateTaskCount = function (task, count) { | |
var zoneDelegates = task._zoneDelegates; | |
if (count == -1) { | |
task._zoneDelegates = null; | |
} | |
for (var i = 0; i < zoneDelegates.length; i++) { | |
zoneDelegates[i]._updateTaskCount(task.type, count); | |
} | |
}; | |
Zone.__symbol__ = __symbol__; | |
return Zone; | |
}()); | |
var DELEGATE_ZS = { | |
name: '', | |
onHasTask: function (delegate, _, target, hasTaskState) { return delegate.hasTask(target, hasTaskState); }, | |
onScheduleTask: function (delegate, _, target, task) { | |
return delegate.scheduleTask(target, task); | |
}, | |
onInvokeTask: function (delegate, _, target, task, applyThis, applyArgs) { | |
return delegate.invokeTask(target, task, applyThis, applyArgs); | |
}, | |
onCancelTask: function (delegate, _, target, task) { return delegate.cancelTask(target, task); } | |
}; | |
var ZoneDelegate = /** @class */ (function () { | |
function ZoneDelegate(zone, parentDelegate, zoneSpec) { | |
this._taskCounts = { 'microTask': 0, 'macroTask': 0, 'eventTask': 0 }; | |
this.zone = zone; | |
this._parentDelegate = parentDelegate; | |
this._forkZS = zoneSpec && (zoneSpec && zoneSpec.onFork ? zoneSpec : parentDelegate._forkZS); | |
this._forkDlgt = zoneSpec && (zoneSpec.onFork ? parentDelegate : parentDelegate._forkDlgt); | |
this._forkCurrZone = zoneSpec && (zoneSpec.onFork ? this.zone : parentDelegate.zone); | |
this._interceptZS = | |
zoneSpec && (zoneSpec.onIntercept ? zoneSpec : parentDelegate._interceptZS); | |
this._interceptDlgt = | |
zoneSpec && (zoneSpec.onIntercept ? parentDelegate : parentDelegate._interceptDlgt); | |
this._interceptCurrZone = | |
zoneSpec && (zoneSpec.onIntercept ? this.zone : parentDelegate.zone); | |
this._invokeZS = zoneSpec && (zoneSpec.onInvoke ? zoneSpec : parentDelegate._invokeZS); | |
this._invokeDlgt = | |
zoneSpec && (zoneSpec.onInvoke ? parentDelegate : parentDelegate._invokeDlgt); | |
this._invokeCurrZone = zoneSpec && (zoneSpec.onInvoke ? this.zone : parentDelegate.zone); | |
this._handleErrorZS = | |
zoneSpec && (zoneSpec.onHandleError ? zoneSpec : parentDelegate._handleErrorZS); | |
this._handleErrorDlgt = | |
zoneSpec && (zoneSpec.onHandleError ? parentDelegate : parentDelegate._handleErrorDlgt); | |
this._handleErrorCurrZone = | |
zoneSpec && (zoneSpec.onHandleError ? this.zone : parentDelegate.zone); | |
this._scheduleTaskZS = | |
zoneSpec && (zoneSpec.onScheduleTask ? zoneSpec : parentDelegate._scheduleTaskZS); | |
this._scheduleTaskDlgt = zoneSpec && | |
(zoneSpec.onScheduleTask ? parentDelegate : parentDelegate._scheduleTaskDlgt); | |
this._scheduleTaskCurrZone = | |
zoneSpec && (zoneSpec.onScheduleTask ? this.zone : parentDelegate.zone); | |
this._invokeTaskZS = | |
zoneSpec && (zoneSpec.onInvokeTask ? zoneSpec : parentDelegate._invokeTaskZS); | |
this._invokeTaskDlgt = | |
zoneSpec && (zoneSpec.onInvokeTask ? parentDelegate : parentDelegate._invokeTaskDlgt); | |
this._invokeTaskCurrZone = | |
zoneSpec && (zoneSpec.onInvokeTask ? this.zone : parentDelegate.zone); | |
this._cancelTaskZS = | |
zoneSpec && (zoneSpec.onCancelTask ? zoneSpec : parentDelegate._cancelTaskZS); | |
this._cancelTaskDlgt = | |
zoneSpec && (zoneSpec.onCancelTask ? parentDelegate : parentDelegate._cancelTaskDlgt); | |
this._cancelTaskCurrZone = | |
zoneSpec && (zoneSpec.onCancelTask ? this.zone : parentDelegate.zone); | |
this._hasTaskZS = null; | |
this._hasTaskDlgt = null; | |
this._hasTaskDlgtOwner = null; | |
this._hasTaskCurrZone = null; | |
var zoneSpecHasTask = zoneSpec && zoneSpec.onHasTask; | |
var parentHasTask = parentDelegate && parentDelegate._hasTaskZS; | |
if (zoneSpecHasTask || parentHasTask) { | |
// If we need to report hasTask, than this ZS needs to do ref counting on tasks. In such | |
// a case all task related interceptors must go through this ZD. We can't short circuit it. | |
this._hasTaskZS = zoneSpecHasTask ? zoneSpec : DELEGATE_ZS; | |
this._hasTaskDlgt = parentDelegate; | |
this._hasTaskDlgtOwner = this; | |
this._hasTaskCurrZone = zone; | |
if (!zoneSpec.onScheduleTask) { | |
this._scheduleTaskZS = DELEGATE_ZS; | |
this._scheduleTaskDlgt = parentDelegate; | |
this._scheduleTaskCurrZone = this.zone; | |
} | |
if (!zoneSpec.onInvokeTask) { | |
this._invokeTaskZS = DELEGATE_ZS; | |
this._invokeTaskDlgt = parentDelegate; | |
this._invokeTaskCurrZone = this.zone; | |
} | |
if (!zoneSpec.onCancelTask) { | |
this._cancelTaskZS = DELEGATE_ZS; | |
this._cancelTaskDlgt = parentDelegate; | |
this._cancelTaskCurrZone = this.zone; | |
} | |
} | |
} | |
ZoneDelegate.prototype.fork = function (targetZone, zoneSpec) { | |
return this._forkZS ? this._forkZS.onFork(this._forkDlgt, this.zone, targetZone, zoneSpec) : | |
new Zone(targetZone, zoneSpec); | |
}; | |
ZoneDelegate.prototype.intercept = function (targetZone, callback, source) { | |
return this._interceptZS ? | |
this._interceptZS.onIntercept(this._interceptDlgt, this._interceptCurrZone, targetZone, callback, source) : | |
callback; | |
}; | |
ZoneDelegate.prototype.invoke = function (targetZone, callback, applyThis, applyArgs, source) { | |
return this._invokeZS ? this._invokeZS.onInvoke(this._invokeDlgt, this._invokeCurrZone, targetZone, callback, applyThis, applyArgs, source) : | |
callback.apply(applyThis, applyArgs); | |
}; | |
ZoneDelegate.prototype.handleError = function (targetZone, error) { | |
return this._handleErrorZS ? | |
this._handleErrorZS.onHandleError(this._handleErrorDlgt, this._handleErrorCurrZone, targetZone, error) : | |
true; | |
}; | |
ZoneDelegate.prototype.scheduleTask = function (targetZone, task) { | |
var returnTask = task; | |
if (this._scheduleTaskZS) { | |
if (this._hasTaskZS) { | |
returnTask._zoneDelegates.push(this._hasTaskDlgtOwner); | |
} | |
returnTask = this._scheduleTaskZS.onScheduleTask(this._scheduleTaskDlgt, this._scheduleTaskCurrZone, targetZone, task); | |
if (!returnTask) | |
returnTask = task; | |
} | |
else { | |
if (task.scheduleFn) { | |
task.scheduleFn(task); | |
} | |
else if (task.type == microTask) { | |
scheduleMicroTask(task); | |
} | |
else { | |
throw new Error('Task is missing scheduleFn.'); | |
} | |
} | |
return returnTask; | |
}; | |
ZoneDelegate.prototype.invokeTask = function (targetZone, task, applyThis, applyArgs) { | |
return this._invokeTaskZS ? this._invokeTaskZS.onInvokeTask(this._invokeTaskDlgt, this._invokeTaskCurrZone, targetZone, task, applyThis, applyArgs) : | |
task.callback.apply(applyThis, applyArgs); | |
}; | |
ZoneDelegate.prototype.cancelTask = function (targetZone, task) { | |
var value; | |
if (this._cancelTaskZS) { | |
value = this._cancelTaskZS.onCancelTask(this._cancelTaskDlgt, this._cancelTaskCurrZone, targetZone, task); | |
} | |
else { | |
if (!task.cancelFn) { | |
throw Error('Task is not cancelable'); | |
} | |
value = task.cancelFn(task); | |
} | |
return value; | |
}; | |
ZoneDelegate.prototype.hasTask = function (targetZone, isEmpty) { | |
// hasTask should not throw error so other ZoneDelegate | |
// can still trigger hasTask callback | |
try { | |
this._hasTaskZS && | |
this._hasTaskZS.onHasTask(this._hasTaskDlgt, this._hasTaskCurrZone, targetZone, isEmpty); | |
} | |
catch (err) { | |
this.handleError(targetZone, err); | |
} | |
}; | |
ZoneDelegate.prototype._updateTaskCount = function (type, count) { | |
var counts = this._taskCounts; | |
var prev = counts[type]; | |
var next = counts[type] = prev + count; | |
if (next < 0) { | |
throw new Error('More tasks executed then were scheduled.'); | |
} | |
if (prev == 0 || next == 0) { | |
var isEmpty = { | |
microTask: counts['microTask'] > 0, | |
macroTask: counts['macroTask'] > 0, | |
eventTask: counts['eventTask'] > 0, | |
change: type | |
}; | |
this.hasTask(this.zone, isEmpty); | |
} | |
}; | |
return ZoneDelegate; | |
}()); | |
var ZoneTask = /** @class */ (function () { | |
function ZoneTask(type, source, callback, options, scheduleFn, cancelFn) { | |
this._zone = null; | |
this.runCount = 0; | |
this._zoneDelegates = null; | |
this._state = 'notScheduled'; | |
this.type = type; | |
this.source = source; | |
this.data = options; | |
this.scheduleFn = scheduleFn; | |
this.cancelFn = cancelFn; | |
this.callback = callback; | |
var self = this; | |
// TODO: @JiaLiPassion options should have interface | |
if (type === eventTask && options && options.useG) { | |
this.invoke = ZoneTask.invokeTask; | |
} | |
else { | |
this.invoke = function () { | |
return ZoneTask.invokeTask.call(global, self, this, arguments); | |
}; | |
} | |
} | |
ZoneTask.invokeTask = function (task, target, args) { | |
if (!task) { | |
task = this; | |
} | |
_numberOfNestedTaskFrames++; | |
try { | |
task.runCount++; | |
return task.zone.runTask(task, target, args); | |
} | |
finally { | |
if (_numberOfNestedTaskFrames == 1) { | |
drainMicroTaskQueue(); | |
} | |
_numberOfNestedTaskFrames--; | |
} | |
}; | |
Object.defineProperty(ZoneTask.prototype, "zone", { | |
get: function () { | |
return this._zone; | |
}, | |
enumerable: true, | |
configurable: true | |
}); | |
Object.defineProperty(ZoneTask.prototype, "state", { | |
get: function () { | |
return this._state; | |
}, | |
enumerable: true, | |
configurable: true | |
}); | |
ZoneTask.prototype.cancelScheduleRequest = function () { | |
this._transitionTo(notScheduled, scheduling); | |
}; | |
ZoneTask.prototype._transitionTo = function (toState, fromState1, fromState2) { | |
if (this._state === fromState1 || this._state === fromState2) { | |
this._state = toState; | |
if (toState == notScheduled) { | |
this._zoneDelegates = null; | |
} | |
} | |
else { | |
throw new Error(this.type + " '" + this.source + "': can not transition to '" + toState + "', expecting state '" + fromState1 + "'" + (fromState2 ? ' or \'' + fromState2 + '\'' : '') + ", was '" + this._state + "'."); | |
} | |
}; | |
ZoneTask.prototype.toString = function () { | |
if (this.data && typeof this.data.handleId !== 'undefined') { | |
return this.data.handleId; | |
} | |
else { | |
return Object.prototype.toString.call(this); | |
} | |
}; | |
// add toJSON method to prevent cyclic error when | |
// call JSON.stringify(zoneTask) | |
ZoneTask.prototype.toJSON = function () { | |
return { | |
type: this.type, | |
state: this.state, | |
source: this.source, | |
zone: this.zone.name, | |
runCount: this.runCount | |
}; | |
}; | |
return ZoneTask; | |
}()); | |
////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////// | |
/// MICROTASK QUEUE | |
////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////// | |
var symbolSetTimeout = __symbol__('setTimeout'); | |
var symbolPromise = __symbol__('Promise'); | |
var symbolThen = __symbol__('then'); | |
var _microTaskQueue = []; | |
var _isDrainingMicrotaskQueue = false; | |
var nativeMicroTaskQueuePromise; | |
function scheduleMicroTask(task) { | |
// if we are not running in any task, and there has not been anything scheduled | |
// we must bootstrap the initial task creation by manually scheduling the drain | |
if (_numberOfNestedTaskFrames === 0 && _microTaskQueue.length === 0) { | |
// We are not running in Task, so we need to kickstart the microtask queue. | |
if (!nativeMicroTaskQueuePromise) { | |
if (global[symbolPromise]) { | |
nativeMicroTaskQueuePromise = global[symbolPromise].resolve(0); | |
} | |
} | |
if (nativeMicroTaskQueuePromise) { | |
var nativeThen = nativeMicroTaskQueuePromise[symbolThen]; | |
if (!nativeThen) { | |
// native Promise is not patchable, we need to use `then` directly | |
// issue 1078 | |
nativeThen = nativeMicroTaskQueuePromise['then']; | |
} | |
nativeThen.call(nativeMicroTaskQueuePromise, drainMicroTaskQueue); | |
} | |
else { | |
global[symbolSetTimeout](drainMicroTaskQueue, 0); | |
} | |
} | |
task && _microTaskQueue.push(task); | |
} | |
function drainMicroTaskQueue() { | |
if (!_isDrainingMicrotaskQueue) { | |
_isDrainingMicrotaskQueue = true; | |
while (_microTaskQueue.length) { | |
var queue = _microTaskQueue; | |
_microTaskQueue = []; | |
for (var i = 0; i < queue.length; i++) { | |
var task = queue[i]; | |
try { | |
task.zone.runTask(task, null, null); | |
} | |
catch (error) { | |
_api.onUnhandledError(error); | |
} | |
} | |
} | |
_api.microtaskDrainDone(); | |
_isDrainingMicrotaskQueue = false; | |
} | |
} | |
////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////// | |
/// BOOTSTRAP | |
////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////// | |
var NO_ZONE = { name: 'NO ZONE' }; | |
var notScheduled = 'notScheduled', scheduling = 'scheduling', scheduled = 'scheduled', running = 'running', canceling = 'canceling', unknown = 'unknown'; | |
var microTask = 'microTask', macroTask = 'macroTask', eventTask = 'eventTask'; | |
var patches = {}; | |
var _api = { | |
symbol: __symbol__, | |
currentZoneFrame: function () { return _currentZoneFrame; }, | |
onUnhandledError: noop, | |
microtaskDrainDone: noop, | |
scheduleMicroTask: scheduleMicroTask, | |
showUncaughtError: function () { return !Zone[__symbol__('ignoreConsoleErrorUncaughtError')]; }, | |
patchEventTarget: function () { return []; }, | |
patchOnProperties: noop, | |
patchMethod: function () { return noop; }, | |
bindArguments: function () { return []; }, | |
patchThen: function () { return noop; }, | |
setNativePromise: function (NativePromise) { | |
// sometimes NativePromise.resolve static function | |
// is not ready yet, (such as core-js/es6.promise) | |
// so we need to check here. | |
if (NativePromise && typeof NativePromise.resolve === 'function') { | |
nativeMicroTaskQueuePromise = NativePromise.resolve(0); | |
} | |
}, | |
}; | |
var _currentZoneFrame = { parent: null, zone: new Zone(null, null) }; | |
var _currentTask = null; | |
var _numberOfNestedTaskFrames = 0; | |
function noop() { } | |
function __symbol__(name) { | |
return '__zone_symbol__' + name; | |
} | |
performanceMeasure('Zone', 'Zone'); | |
return global['Zone'] = Zone; | |
})(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global); | |
Zone.__load_patch('ZoneAwarePromise', function (global, Zone, api) { | |
var ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; | |
var ObjectDefineProperty = Object.defineProperty; | |
function readableObjectToString(obj) { | |
if (obj && obj.toString === Object.prototype.toString) { | |
var className = obj.constructor && obj.constructor.name; | |
return (className ? className : '') + ': ' + JSON.stringify(obj); | |
} | |
return obj ? obj.toString() : Object.prototype.toString.call(obj); | |
} | |
var __symbol__ = api.symbol; | |
var _uncaughtPromiseErrors = []; | |
var symbolPromise = __symbol__('Promise'); | |
var symbolThen = __symbol__('then'); | |
var creationTrace = '__creationTrace__'; | |
api.onUnhandledError = function (e) { | |
if (api.showUncaughtError()) { | |
var rejection = e && e.rejection; | |
if (rejection) { | |
console.error('Unhandled Promise rejection:', rejection instanceof Error ? rejection.message : rejection, '; Zone:', e.zone.name, '; Task:', e.task && e.task.source, '; Value:', rejection, rejection instanceof Error ? rejection.stack : undefined); | |
} | |
else { | |
console.error(e); | |
} | |
} | |
}; | |
api.microtaskDrainDone = function () { | |
while (_uncaughtPromiseErrors.length) { | |
var _loop_1 = function () { | |
var uncaughtPromiseError = _uncaughtPromiseErrors.shift(); | |
try { | |
uncaughtPromiseError.zone.runGuarded(function () { | |
throw uncaughtPromiseError; | |
}); | |
} | |
catch (error) { | |
handleUnhandledRejection(error); | |
} | |
}; | |
while (_uncaughtPromiseErrors.length) { | |
_loop_1(); | |
} | |
} | |
}; | |
var UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL = __symbol__('unhandledPromiseRejectionHandler'); | |
function handleUnhandledRejection(e) { | |
api.onUnhandledError(e); | |
try { | |
var handler = Zone[UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL]; | |
if (handler && typeof handler === 'function') { | |
handler.call(this, e); | |
} | |
} | |
catch (err) { | |
} | |
} | |
function isThenable(value) { | |
return value && value.then; | |
} | |
function forwardResolution(value) { | |
return value; | |
} | |
function forwardRejection(rejection) { | |
return ZoneAwarePromise.reject(rejection); | |
} | |
var symbolState = __symbol__('state'); | |
var symbolValue = __symbol__('value'); | |
var symbolFinally = __symbol__('finally'); | |
var symbolParentPromiseValue = __symbol__('parentPromiseValue'); | |
var symbolParentPromiseState = __symbol__('parentPromiseState'); | |
var source = 'Promise.then'; | |
var UNRESOLVED = null; | |
var RESOLVED = true; | |
var REJECTED = false; | |
var REJECTED_NO_CATCH = 0; | |
function makeResolver(promise, state) { | |
return function (v) { | |
try { | |
resolvePromise(promise, state, v); | |
} | |
catch (err) { | |
resolvePromise(promise, false, err); | |
} | |
// Do not return value or you will break the Promise spec. | |
}; | |
} | |
var once = function () { | |
var wasCalled = false; | |
return function wrapper(wrappedFunction) { | |
return function () { | |
if (wasCalled) { | |
return; | |
} | |
wasCalled = true; | |
wrappedFunction.apply(null, arguments); | |
}; | |
}; | |
}; | |
var TYPE_ERROR = 'Promise resolved with itself'; | |
var CURRENT_TASK_TRACE_SYMBOL = __symbol__('currentTaskTrace'); | |
// Promise Resolution | |
function resolvePromise(promise, state, value) { | |
var onceWrapper = once(); | |
if (promise === value) { | |
throw new TypeError(TYPE_ERROR); | |
} | |
if (promise[symbolState] === UNRESOLVED) { | |
// should only get value.then once based on promise spec. | |
var then = null; | |
try { | |
if (typeof value === 'object' || typeof value === 'function') { | |
then = value && value.then; | |
} | |
} | |
catch (err) { | |
onceWrapper(function () { | |
resolvePromise(promise, false, err); | |
})(); | |
return promise; | |
} | |
// if (value instanceof ZoneAwarePromise) { | |
if (state !== REJECTED && value instanceof ZoneAwarePromise && | |
value.hasOwnProperty(symbolState) && value.hasOwnProperty(symbolValue) && | |
value[symbolState] !== UNRESOLVED) { | |
clearRejectedNoCatch(value); | |
resolvePromise(promise, value[symbolState], value[symbolValue]); | |
} | |
else if (state !== REJECTED && typeof then === 'function') { | |
try { | |
then.call(value, onceWrapper(makeResolver(promise, state)), onceWrapper(makeResolver(promise, false))); | |
} | |
catch (err) { | |
onceWrapper(function () { | |
resolvePromise(promise, false, err); | |
})(); | |
} | |
} | |
else { | |
promise[symbolState] = state; | |
var queue = promise[symbolValue]; | |
promise[symbolValue] = value; | |
if (promise[symbolFinally] === symbolFinally) { | |
// the promise is generated by Promise.prototype.finally | |
if (state === RESOLVED) { | |
// the state is resolved, should ignore the value | |
// and use parent promise value | |
promise[symbolState] = promise[symbolParentPromiseState]; | |
promise[symbolValue] = promise[symbolParentPromiseValue]; | |
} | |
} | |
// record task information in value when error occurs, so we can | |
// do some additional work such as render longStackTrace | |
if (state === REJECTED && value instanceof Error) { | |
// check if longStackTraceZone is here | |
var trace = Zone.currentTask && Zone.currentTask.data && | |
Zone.currentTask.data[creationTrace]; | |
if (trace) { | |
// only keep the long stack trace into error when in longStackTraceZone | |
ObjectDefineProperty(value, CURRENT_TASK_TRACE_SYMBOL, { configurable: true, enumerable: false, writable: true, value: trace }); | |
} | |
} | |
for (var i = 0; i < queue.length;) { | |
scheduleResolveOrReject(promise, queue[i++], queue[i++], queue[i++], queue[i++]); | |
} | |
if (queue.length == 0 && state == REJECTED) { | |
promise[symbolState] = REJECTED_NO_CATCH; | |
try { | |
// try to print more readable error log | |
throw new Error('Uncaught (in promise): ' + readableObjectToString(value) + | |
(value && value.stack ? '\n' + value.stack : '')); | |
} | |
catch (err) { | |
var error_1 = err; | |
error_1.rejection = value; | |
error_1.promise = promise; | |
error_1.zone = Zone.current; | |
error_1.task = Zone.currentTask; | |
_uncaughtPromiseErrors.push(error_1); | |
api.scheduleMicroTask(); // to make sure that it is running | |
} | |
} | |
} | |
} | |
// Resolving an already resolved promise is a noop. | |
return promise; | |
} | |
var REJECTION_HANDLED_HANDLER = __symbol__('rejectionHandledHandler'); | |
function clearRejectedNoCatch(promise) { | |
if (promise[symbolState] === REJECTED_NO_CATCH) { | |
// if the promise is rejected no catch status | |
// and queue.length > 0, means there is a error handler | |
// here to handle the rejected promise, we should trigger | |
// windows.rejectionhandled eventHandler or nodejs rejectionHandled | |
// eventHandler | |
try { | |
var handler = Zone[REJECTION_HANDLED_HANDLER]; | |
if (handler && typeof handler === 'function') { | |
handler.call(this, { rejection: promise[symbolValue], promise: promise }); | |
} | |
} | |
catch (err) { | |
} | |
promise[symbolState] = REJECTED; | |
for (var i = 0; i < _uncaughtPromiseErrors.length; i++) { | |
if (promise === _uncaughtPromiseErrors[i].promise) { | |
_uncaughtPromiseErrors.splice(i, 1); | |
} | |
} | |
} | |
} | |
function scheduleResolveOrReject(promise, zone, chainPromise, onFulfilled, onRejected) { | |
clearRejectedNoCatch(promise); | |
var promiseState = promise[symbolState]; | |
var delegate = promiseState ? | |
(typeof onFulfilled === 'function') ? onFulfilled : forwardResolution : | |
(typeof onRejected === 'function') ? onRejected : forwardRejection; | |
zone.scheduleMicroTask(source, function () { | |
try { | |
var parentPromiseValue = promise[symbolValue]; | |
var isFinallyPromise = chainPromise && symbolFinally === chainPromise[symbolFinally]; | |
if (isFinallyPromise) { | |
// if the promise is generated from finally call, keep parent promise's state and value | |
chainPromise[symbolParentPromiseValue] = parentPromiseValue; | |
chainPromise[symbolParentPromiseState] = promiseState; | |
} | |
// should not pass value to finally callback | |
var value = zone.run(delegate, undefined, isFinallyPromise && delegate !== forwardRejection && delegate !== forwardResolution ? | |
[] : | |
[parentPromiseValue]); | |
resolvePromise(chainPromise, true, value); | |
} | |
catch (error) { | |
// if error occurs, should always return this error | |
resolvePromise(chainPromise, false, error); | |
} | |
}, chainPromise); | |
} | |
var ZONE_AWARE_PROMISE_TO_STRING = 'function ZoneAwarePromise() { [native code] }'; | |
var ZoneAwarePromise = /** @class */ (function () { | |
function ZoneAwarePromise(executor) { | |
var promise = this; | |
if (!(promise instanceof ZoneAwarePromise)) { | |
throw new Error('Must be an instanceof Promise.'); | |
} | |
promise[symbolState] = UNRESOLVED; | |
promise[symbolValue] = []; // queue; | |
try { | |
executor && executor(makeResolver(promise, RESOLVED), makeResolver(promise, REJECTED)); | |
} | |
catch (error) { | |
resolvePromise(promise, false, error); | |
} | |
} | |
ZoneAwarePromise.toString = function () { | |
return ZONE_AWARE_PROMISE_TO_STRING; | |
}; | |
ZoneAwarePromise.resolve = function (value) { | |
return resolvePromise(new this(null), RESOLVED, value); | |
}; | |
ZoneAwarePromise.reject = function (error) { | |
return resolvePromise(new this(null), REJECTED, error); | |
}; | |
ZoneAwarePromise.race = function (values) { | |
var resolve; | |
var reject; | |
var promise = new this(function (res, rej) { | |
resolve = res; | |
reject = rej; | |
}); | |
function onResolve(value) { | |
promise && (promise = null || resolve(value)); | |
} | |
function onReject(error) { | |
promise && (promise = null || reject(error)); | |
} | |
for (var _i = 0, values_1 = values; _i < values_1.length; _i++) { | |
var value = values_1[_i]; | |
if (!isThenable(value)) { | |
value = this.resolve(value); | |
} | |
value.then(onResolve, onReject); | |
} | |
return promise; | |
}; | |
ZoneAwarePromise.all = function (values) { | |
var resolve; | |
var reject; | |
var promise = new this(function (res, rej) { | |
resolve = res; | |
reject = rej; | |
}); | |
var count = 0; | |
var resolvedValues = []; | |
for (var _i = 0, values_2 = values; _i < values_2.length; _i++) { | |
var value = values_2[_i]; | |
if (!isThenable(value)) { | |
value = this.resolve(value); | |
} | |
value.then((function (index) { return function (value) { | |
resolvedValues[index] = value; | |
count--; | |
if (!count) { | |
resolve(resolvedValues); | |
} | |
}; })(count), reject); | |
count++; | |
} | |
if (!count) | |
resolve(resolvedValues); | |
return promise; | |
}; | |
ZoneAwarePromise.prototype.then = function (onFulfilled, onRejected) { | |
var chainPromise = new this.constructor(null); | |
var zone = Zone.current; | |
if (this[symbolState] == UNRESOLVED) { | |
this[symbolValue].push(zone, chainPromise, onFulfilled, onRejected); | |
} | |
else { | |
scheduleResolveOrReject(this, zone, chainPromise, onFulfilled, onRejected); | |
} | |
return chainPromise; | |
}; | |
ZoneAwarePromise.prototype.catch = function (onRejected) { | |
return this.then(null, onRejected); | |
}; | |
ZoneAwarePromise.prototype.finally = function (onFinally) { | |
var chainPromise = new this.constructor(null); | |
chainPromise[symbolFinally] = symbolFinally; | |
var zone = Zone.current; | |
if (this[symbolState] == UNRESOLVED) { | |
this[symbolValue].push(zone, chainPromise, onFinally, onFinally); | |
} | |
else { | |
scheduleResolveOrReject(this, zone, chainPromise, onFinally, onFinally); | |
} | |
return chainPromise; | |
}; | |
return ZoneAwarePromise; | |
}()); | |
// Protect against aggressive optimizers dropping seemingly unused properties. | |
// E.g. Closure Compiler in advanced mode. | |
ZoneAwarePromise['resolve'] = ZoneAwarePromise.resolve; | |
ZoneAwarePromise['reject'] = ZoneAwarePromise.reject; | |
ZoneAwarePromise['race'] = ZoneAwarePromise.race; | |
ZoneAwarePromise['all'] = ZoneAwarePromise.all; | |
var NativePromise = global[symbolPromise] = global['Promise']; | |
var ZONE_AWARE_PROMISE = Zone.__symbol__('ZoneAwarePromise'); | |
var desc = ObjectGetOwnPropertyDescriptor(global, 'Promise'); | |
if (!desc || desc.configurable) { | |
desc && delete desc.writable; | |
desc && delete desc.value; | |
if (!desc) { | |
desc = { configurable: true, enumerable: true }; | |
} | |
desc.get = function () { | |
// if we already set ZoneAwarePromise, use patched one | |
// otherwise return native one. | |
return global[ZONE_AWARE_PROMISE] ? global[ZONE_AWARE_PROMISE] : global[symbolPromise]; | |
}; | |
desc.set = function (NewNativePromise) { | |
if (NewNativePromise === ZoneAwarePromise) { | |
// if the NewNativePromise is ZoneAwarePromise | |
// save to global | |
global[ZONE_AWARE_PROMISE] = NewNativePromise; | |
} | |
else { | |
// if the NewNativePromise is not ZoneAwarePromise | |
// for example: after load zone.js, some library just | |
// set es6-promise to global, if we set it to global | |
// directly, assertZonePatched will fail and angular | |
// will not loaded, so we just set the NewNativePromise | |
// to global[symbolPromise], so the result is just like | |
// we load ES6 Promise before zone.js | |
global[symbolPromise] = NewNativePromise; | |
if (!NewNativePromise.prototype[symbolThen]) { | |
patchThen(NewNativePromise); | |
} | |
api.setNativePromise(NewNativePromise); | |
} | |
}; | |
ObjectDefineProperty(global, 'Promise', desc); | |
} | |
global['Promise'] = ZoneAwarePromise; | |
var symbolThenPatched = __symbol__('thenPatched'); | |
function patchThen(Ctor) { | |
var proto = Ctor.prototype; | |
var prop = ObjectGetOwnPropertyDescriptor(proto, 'then'); | |
if (prop && (prop.writable === false || !prop.configurable)) { | |
// check Ctor.prototype.then propertyDescriptor is writable or not | |
// in meteor env, writable is false, we should ignore such case | |
return; | |
} | |
var originalThen = proto.then; | |
// Keep a reference to the original method. | |
proto[symbolThen] = originalThen; | |
Ctor.prototype.then = function (onResolve, onReject) { | |
var _this = this; | |
var wrapped = new ZoneAwarePromise(function (resolve, reject) { | |
originalThen.call(_this, resolve, reject); | |
}); | |
return wrapped.then(onResolve, onReject); | |
}; | |
Ctor[symbolThenPatched] = true; | |
} | |
api.patchThen = patchThen; | |
if (NativePromise) { | |
patchThen(NativePromise); | |
} | |
// This is not part of public API, but it is useful for tests, so we expose it. | |
Promise[Zone.__symbol__('uncaughtPromiseErrors')] = _uncaughtPromiseErrors; | |
return ZoneAwarePromise; | |
}); | |
/** | |
* @license | |
* Copyright Google Inc. All Rights Reserved. | |
* | |
* Use of this source code is governed by an MIT-style license that can be | |
* found in the LICENSE file at https://angular.io/license | |
*/ | |
Zone.__load_patch('fetch', function (global, Zone, api) { | |
var fetch = global['fetch']; | |
var ZoneAwarePromise = global.Promise; | |
var symbolThenPatched = api.symbol('thenPatched'); | |
var fetchTaskScheduling = api.symbol('fetchTaskScheduling'); | |
var fetchTaskAborting = api.symbol('fetchTaskAborting'); | |
if (typeof fetch !== 'function') { | |
return; | |
} | |
var OriginalAbortController = global['AbortController']; | |
var supportAbort = typeof OriginalAbortController === 'function'; | |
var abortNative = null; | |
if (supportAbort) { | |
global['AbortController'] = function () { | |
var abortController = new OriginalAbortController(); | |
var signal = abortController.signal; | |
signal.abortController = abortController; | |
return abortController; | |
}; | |
abortNative = api.patchMethod(OriginalAbortController.prototype, 'abort', function (delegate) { return function (self, args) { | |
if (self.task) { | |
return self.task.zone.cancelTask(self.task); | |
} | |
return delegate.apply(self, args); | |
}; }); | |
} | |
var placeholder = function () { }; | |
global['fetch'] = function () { | |
var _this = this; | |
var args = Array.prototype.slice.call(arguments); | |
var options = args.length > 1 ? args[1] : null; | |
var signal = options && options.signal; | |
return new Promise(function (res, rej) { | |
var task = Zone.current.scheduleMacroTask('fetch', placeholder, args, function () { | |
var fetchPromise; | |
var zone = Zone.current; | |
try { | |
zone[fetchTaskScheduling] = true; | |
fetchPromise = fetch.apply(_this, args); | |
} | |
catch (error) { | |
rej(error); | |
return; | |
} | |
finally { | |
zone[fetchTaskScheduling] = false; | |
} | |
if (!(fetchPromise instanceof ZoneAwarePromise)) { | |
var ctor = fetchPromise.constructor; | |
if (!ctor[symbolThenPatched]) { | |
api.patchThen(ctor); | |
} | |
} | |
fetchPromise.then(function (resource) { | |
if (task.state !== 'notScheduled') { | |
task.invoke(); | |
} | |
res(resource); | |
}, function (error) { | |
if (task.state !== 'notScheduled') { | |
task.invoke(); | |
} | |
rej(error); | |
}); | |
}, function () { | |
if (!supportAbort) { | |
rej('No AbortController supported, can not cancel fetch'); | |
return; | |
} | |
if (signal && signal.abortController && !signal.aborted && | |
typeof signal.abortController.abort === 'function' && abortNative) { | |
try { | |
Zone.current[fetchTaskAborting] = true; | |
abortNative.call(signal.abortController); | |
} | |
finally { | |
Zone.current[fetchTaskAborting] = false; | |
} | |
} | |
else { | |
rej('cancel fetch need a AbortController.signal'); | |
} | |
}); | |
if (signal && signal.abortController) { | |
signal.abortController.task = task; | |
} | |
}); | |
}; | |
}); | |
/** | |
* @license | |
* Copyright Google Inc. All Rights Reserved. | |
* | |
* Use of this source code is governed by an MIT-style license that can be | |
* found in the LICENSE file at https://angular.io/license | |
*/ | |
/** | |
* Suppress closure compiler errors about unknown 'Zone' variable | |
* @fileoverview | |
* @suppress {undefinedVars,globalThis,missingRequire} | |
*/ | |
// issue #989, to reduce bundle size, use short name | |
/** Object.getOwnPropertyDescriptor */ | |
var ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; | |
/** Object.defineProperty */ | |
var ObjectDefineProperty = Object.defineProperty; | |
/** Object.getPrototypeOf */ | |
var ObjectGetPrototypeOf = Object.getPrototypeOf; | |
/** Object.create */ | |
var ObjectCreate = Object.create; | |
/** Array.prototype.slice */ | |
var ArraySlice = Array.prototype.slice; | |
/** addEventListener string const */ | |
var ADD_EVENT_LISTENER_STR = 'addEventListener'; | |
/** removeEventListener string const */ | |
var REMOVE_EVENT_LISTENER_STR = 'removeEventListener'; | |
/** zoneSymbol addEventListener */ | |
var ZONE_SYMBOL_ADD_EVENT_LISTENER = Zone.__symbol__(ADD_EVENT_LISTENER_STR); | |
/** zoneSymbol removeEventListener */ | |
var ZONE_SYMBOL_REMOVE_EVENT_LISTENER = Zone.__symbol__(REMOVE_EVENT_LISTENER_STR); | |
/** true string const */ | |
var TRUE_STR = 'true'; | |
/** false string const */ | |
var FALSE_STR = 'false'; | |
/** __zone_symbol__ string const */ | |
var ZONE_SYMBOL_PREFIX = '__zone_symbol__'; | |
function wrapWithCurrentZone(callback, source) { | |
return Zone.current.wrap(callback, source); | |
} | |
function scheduleMacroTaskWithCurrentZone(source, callback, data, customSchedule, customCancel) { | |
return Zone.current.scheduleMacroTask(source, callback, data, customSchedule, customCancel); | |
} | |
var zoneSymbol = Zone.__symbol__; | |
var isWindowExists = typeof window !== 'undefined'; | |
var internalWindow = isWindowExists ? window : undefined; | |
var _global = isWindowExists && internalWindow || typeof self === 'object' && self || global; | |
var REMOVE_ATTRIBUTE = 'removeAttribute'; | |
var NULL_ON_PROP_VALUE = [null]; | |
function bindArguments(args, source) { | |
for (var i = args.length - 1; i >= 0; i--) { | |
if (typeof args[i] === 'function') { | |
args[i] = wrapWithCurrentZone(args[i], source + '_' + i); | |
} | |
} | |
return args; | |
} | |
function patchPrototype(prototype, fnNames) { | |
var source = prototype.constructor['name']; | |
var _loop_1 = function (i) { | |
var name_1 = fnNames[i]; | |
var delegate = prototype[name_1]; | |
if (delegate) { | |
var prototypeDesc = ObjectGetOwnPropertyDescriptor(prototype, name_1); | |
if (!isPropertyWritable(prototypeDesc)) { | |
return "continue"; | |
} | |
prototype[name_1] = (function (delegate) { | |
var patched = function () { | |
return delegate.apply(this, bindArguments(arguments, source + '.' + name_1)); | |
}; | |
attachOriginToPatched(patched, delegate); | |
return patched; | |
})(delegate); | |
} | |
}; | |
for (var i = 0; i < fnNames.length; i++) { | |
_loop_1(i); | |
} | |
} | |
function isPropertyWritable(propertyDesc) { | |
if (!propertyDesc) { | |
return true; | |
} | |
if (propertyDesc.writable === false) { | |
return false; | |
} | |
return !(typeof propertyDesc.get === 'function' && typeof propertyDesc.set === 'undefined'); | |
} | |
var isWebWorker = (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope); | |
// Make sure to access `process` through `_global` so that WebPack does not accidentally browserify | |
// this code. | |
var isNode = (!('nw' in _global) && typeof _global.process !== 'undefined' && | |
{}.toString.call(_global.process) === '[object process]'); | |
var isBrowser = !isNode && !isWebWorker && !!(isWindowExists && internalWindow['HTMLElement']); | |
// we are in electron of nw, so we are both browser and nodejs | |
// Make sure to access `process` through `_global` so that WebPack does not accidentally browserify | |
// this code. | |
var isMix = typeof _global.process !== 'undefined' && | |
{}.toString.call(_global.process) === '[object process]' && !isWebWorker && | |
!!(isWindowExists && internalWindow['HTMLElement']); | |
var zoneSymbolEventNames = {}; | |
var wrapFn = function (event) { | |
// https://github.com/angular/zone.js/issues/911, in IE, sometimes | |
// event will be undefined, so we need to use window.event | |
event = event || _global.event; | |
if (!event) { | |
return; | |
} | |
var eventNameSymbol = zoneSymbolEventNames[event.type]; | |
if (!eventNameSymbol) { | |
eventNameSymbol = zoneSymbolEventNames[event.type] = zoneSymbol('ON_PROPERTY' + event.type); | |
} | |
var target = this || event.target || _global; | |
var listener = target[eventNameSymbol]; | |
var result; | |
if (isBrowser && target === internalWindow && event.type === 'error') { | |
// window.onerror have different signiture | |
// https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror#window.onerror | |
// and onerror callback will prevent default when callback return true | |
var errorEvent = event; | |
result = listener && | |
listener.call(this, errorEvent.message, errorEvent.filename, errorEvent.lineno, errorEvent.colno, errorEvent.error); | |
if (result === true) { | |
event.preventDefault(); | |
} | |
} | |
else { | |
result = listener && listener.apply(this, arguments); | |
if (result != undefined && !result) { | |
event.preventDefault(); | |
} | |
} | |
return result; | |
}; | |
function patchProperty(obj, prop, prototype) { | |
var desc = ObjectGetOwnPropertyDescriptor(obj, prop); | |
if (!desc && prototype) { | |
// when patch window object, use prototype to check prop exist or not | |
var prototypeDesc = ObjectGetOwnPropertyDescriptor(prototype, prop); | |
if (prototypeDesc) { | |
desc = { enumerable: true, configurable: true }; | |
} | |
} | |
// if the descriptor not exists or is not configurable | |
// just return | |
if (!desc || !desc.configurable) { | |
return; | |
} | |
var onPropPatchedSymbol = zoneSymbol('on' + prop + 'patched'); | |
if (obj.hasOwnProperty(onPropPatchedSymbol) && obj[onPropPatchedSymbol]) { | |
return; | |
} | |
// A property descriptor cannot have getter/setter and be writable | |
// deleting the writable and value properties avoids this error: | |
// | |
// TypeError: property descriptors must not specify a value or be writable when a | |
// getter or setter has been specified | |
delete desc.writable; | |
delete desc.value; | |
var originalDescGet = desc.get; | |
var originalDescSet = desc.set; | |
// substr(2) cuz 'onclick' -> 'click', etc | |
var eventName = prop.substr(2); | |
var eventNameSymbol = zoneSymbolEventNames[eventName]; | |
if (!eventNameSymbol) { | |
eventNameSymbol = zoneSymbolEventNames[eventName] = zoneSymbol('ON_PROPERTY' + eventName); | |
} | |
desc.set = function (newValue) { | |
// in some of windows's onproperty callback, this is undefined | |
// so we need to check it | |
var target = this; | |
if (!target && obj === _global) { | |
target = _global; | |
} | |
if (!target) { | |
return; | |
} | |
var previousValue = target[eventNameSymbol]; | |
if (previousValue) { | |
target.removeEventListener(eventName, wrapFn); | |
} | |
// issue #978, when onload handler was added before loading zone.js | |
// we should remove it with originalDescSet | |
if (originalDescSet) { | |
originalDescSet.apply(target, NULL_ON_PROP_VALUE); | |
} | |
if (typeof newValue === 'function') { | |
target[eventNameSymbol] = newValue; | |
target.addEventListener(eventName, wrapFn, false); | |
} | |
else { | |
target[eventNameSymbol] = null; | |
} | |
}; | |
// The getter would return undefined for unassigned properties but the default value of an | |
// unassigned property is null | |
desc.get = function () { | |
// in some of windows's onproperty callback, this is undefined | |
// so we need to check it | |
var target = this; | |
if (!target && obj === _global) { | |
target = _global; | |
} | |
if (!target) { | |
return null; | |
} | |
var listener = target[eventNameSymbol]; | |
if (listener) { | |
return listener; | |
} | |
else if (originalDescGet) { | |
// result will be null when use inline event attribute, | |
// such as <button onclick="func();">OK</button> | |
// because the onclick function is internal raw uncompiled handler | |
// the onclick will be evaluated when first time event was triggered or | |
// the property is accessed, https://github.com/angular/zone.js/issues/525 | |
// so we should use original native get to retrieve the handler | |
var value = originalDescGet && originalDescGet.call(this); | |
if (value) { | |
desc.set.call(this, value); | |
if (typeof target[REMOVE_ATTRIBUTE] === 'function') { | |
target.removeAttribute(prop); | |
} | |
return value; | |
} | |
} | |
return null; | |
}; | |
ObjectDefineProperty(obj, prop, desc); | |
obj[onPropPatchedSymbol] = true; | |
} | |
function patchOnProperties(obj, properties, prototype) { | |
if (properties) { | |
for (var i = 0; i < properties.length; i++) { | |
patchProperty(obj, 'on' + properties[i], prototype); | |
} | |
} | |
else { | |
var onProperties = []; | |
for (var prop in obj) { | |
if (prop.substr(0, 2) == 'on') { | |
onProperties.push(prop); | |
} | |
} | |
for (var j = 0; j < onProperties.length; j++) { | |
patchProperty(obj, onProperties[j], prototype); | |
} | |
} | |
} | |
var originalInstanceKey = zoneSymbol('originalInstance'); | |
// wrap some native API on `window` | |
function patchClass(className) { | |
var OriginalClass = _global[className]; | |
if (!OriginalClass) | |
return; | |
// keep original class in global | |
_global[zoneSymbol(className)] = OriginalClass; | |
_global[className] = function () { | |
var a = bindArguments(arguments, className); | |
switch (a.length) { | |
case 0: | |
this[originalInstanceKey] = new OriginalClass(); | |
break; | |
case 1: | |
this[originalInstanceKey] = new OriginalClass(a[0]); | |
break; | |
case 2: | |
this[originalInstanceKey] = new OriginalClass(a[0], a[1]); | |
break; | |
case 3: | |
this[originalInstanceKey] = new OriginalClass(a[0], a[1], a[2]); | |
break; | |
case 4: | |
this[originalInstanceKey] = new OriginalClass(a[0], a[1], a[2], a[3]); | |
break; | |
default: | |
throw new Error('Arg list too long.'); | |
} | |
}; | |
// attach original delegate to patched function | |
attachOriginToPatched(_global[className], OriginalClass); | |
var instance = new OriginalClass(function () { }); | |
var prop; | |
for (prop in instance) { | |
// https://bugs.webkit.org/show_bug.cgi?id=44721 | |
if (className === 'XMLHttpRequest' && prop === 'responseBlob') | |
continue; | |
(function (prop) { | |
if (typeof instance[prop] === 'function') { | |
_global[className].prototype[prop] = function () { | |
return this[originalInstanceKey][prop].apply(this[originalInstanceKey], arguments); | |
}; | |
} | |
else { | |
ObjectDefineProperty(_global[className].prototype, prop, { | |
set: function (fn) { | |
if (typeof fn === 'function') { | |
this[originalInstanceKey][prop] = wrapWithCurrentZone(fn, className + '.' + prop); | |
// keep callback in wrapped function so we can | |
// use it in Function.prototype.toString to return | |
// the native one. | |
attachOriginToPatched(this[originalInstanceKey][prop], fn); | |
} | |
else { | |
this[originalInstanceKey][prop] = fn; | |
} | |
}, | |
get: function () { | |
return this[originalInstanceKey][prop]; | |
} | |
}); | |
} | |
}(prop)); | |
} | |
for (prop in OriginalClass) { | |
if (prop !== 'prototype' && OriginalClass.hasOwnProperty(prop)) { | |
_global[className][prop] = OriginalClass[prop]; | |
} | |
} | |
} | |
function copySymbolProperties(src, dest) { | |
if (typeof Object.getOwnPropertySymbols !== 'function') { | |
return; | |
} | |
var symbols = Object.getOwnPropertySymbols(src); | |
symbols.forEach(function (symbol) { | |
var desc = Object.getOwnPropertyDescriptor(src, symbol); | |
Object.defineProperty(dest, symbol, { | |
get: function () { | |
return src[symbol]; | |
}, | |
set: function (value) { | |
if (desc && (!desc.writable || typeof desc.set !== 'function')) { | |
// if src[symbol] is not writable or not have a setter, just return | |
return; | |
} | |
src[symbol] = value; | |
}, | |
enumerable: desc ? desc.enumerable : true, | |
configurable: desc ? desc.configurable : true | |
}); | |
}); | |
} | |
var shouldCopySymbolProperties = false; | |
function patchMethod(target, name, patchFn) { | |
var proto = target; | |
while (proto && !proto.hasOwnProperty(name)) { | |
proto = ObjectGetPrototypeOf(proto); | |
} | |
if (!proto && target[name]) { | |
// somehow we did not find it, but we can see it. This happens on IE for Window properties. | |
proto = target; | |
} | |
var delegateName = zoneSymbol(name); | |
var delegate = null; | |
if (proto && !(delegate = proto[delegateName])) { | |
delegate = proto[delegateName] = proto[name]; | |
// check whether proto[name] is writable | |
// some property is readonly in safari, such as HtmlCanvasElement.prototype.toBlob | |
var desc = proto && ObjectGetOwnPropertyDescriptor(proto, name); | |
if (isPropertyWritable(desc)) { | |
var patchDelegate_1 = patchFn(delegate, delegateName, name); | |
proto[name] = function () { | |
return patchDelegate_1(this, arguments); | |
}; | |
attachOriginToPatched(proto[name], delegate); | |
if (shouldCopySymbolProperties) { | |
copySymbolProperties(delegate, proto[name]); | |
} | |
} | |
} | |
return delegate; | |
} | |
// TODO: @JiaLiPassion, support cancel task later if necessary | |
function patchMacroTask(obj, funcName, metaCreator) { | |
var setNative = null; | |
function scheduleTask(task) { | |
var data = task.data; | |
data.args[data.cbIdx] = function () { | |
task.invoke.apply(this, arguments); | |
}; | |
setNative.apply(data.target, data.args); | |
return task; | |
} | |
setNative = patchMethod(obj, funcName, function (delegate) { return function (self, args) { | |
var meta = metaCreator(self, args); | |
if (meta.cbIdx >= 0 && typeof args[meta.cbIdx] === 'function') { | |
return scheduleMacroTaskWithCurrentZone(meta.name, args[meta.cbIdx], meta, scheduleTask); | |
} | |
else { | |
// cause an error by calling it directly. | |
return delegate.apply(self, args); | |
} | |
}; }); | |
} | |
function attachOriginToPatched(patched, original) { | |
patched[zoneSymbol('OriginalDelegate')] = original; | |
} | |
var isDetectedIEOrEdge = false; | |
var ieOrEdge = false; | |
function isIE() { | |
try { | |
var ua = internalWindow.navigator.userAgent; | |
if (ua.indexOf('MSIE ') !== -1 || ua.indexOf('Trident/') !== -1) { | |
return true; | |
} | |
} | |
catch (error) { | |
} | |
return false; | |
} | |
function isIEOrEdge() { | |
if (isDetectedIEOrEdge) { | |
return ieOrEdge; | |
} | |
isDetectedIEOrEdge = true; | |
try { | |
var ua = internalWindow.navigator.userAgent; | |
if (ua.indexOf('MSIE ') !== -1 || ua.indexOf('Trident/') !== -1 || ua.indexOf('Edge/') !== -1) { | |
ieOrEdge = true; | |
} | |
return ieOrEdge; | |
} | |
catch (error) { | |
} | |
} | |
/** | |
* @license | |
* Copyright Google Inc. All Rights Reserved. | |
* | |
* Use of this source code is governed by an MIT-style license that can be | |
* found in the LICENSE file at https://angular.io/license | |
*/ | |
// override Function.prototype.toString to make zone.js patched function | |
// look like native function | |
Zone.__load_patch('toString', function (global) { | |
// patch Func.prototype.toString to let them look like native | |
var originalFunctionToString = Function.prototype.toString; | |
var ORIGINAL_DELEGATE_SYMBOL = zoneSymbol('OriginalDelegate'); | |
var PROMISE_SYMBOL = zoneSymbol('Promise'); | |
var ERROR_SYMBOL = zoneSymbol('Error'); | |
var newFunctionToString = function toString() { | |
if (typeof this === 'function') { | |
var originalDelegate = this[ORIGINAL_DELEGATE_SYMBOL]; | |
if (originalDelegate) { | |
if (typeof originalDelegate === 'function') { | |
return originalFunctionToString.apply(this[ORIGINAL_DELEGATE_SYMBOL], arguments); | |
} | |
else { | |
return Object.prototype.toString.call(originalDelegate); | |
} | |
} | |
if (this === Promise) { | |
var nativePromise = global[PROMISE_SYMBOL]; | |
if (nativePromise) { | |
return originalFunctionToString.apply(nativePromise, arguments); | |
} | |
} | |
if (this === Error) { | |
var nativeError = global[ERROR_SYMBOL]; | |
if (nativeError) { | |
return originalFunctionToString.apply(nativeError, arguments); | |
} | |
} | |
} | |
return originalFunctionToString.apply(this, arguments); | |
}; | |
newFunctionToString[ORIGINAL_DELEGATE_SYMBOL] = originalFunctionToString; | |
Function.prototype.toString = newFunctionToString; | |
// patch Object.prototype.toString to let them look like native | |
var originalObjectToString = Object.prototype.toString; | |
var PROMISE_OBJECT_TO_STRING = '[object Promise]'; | |
Object.prototype.toString = function () { | |
if (this instanceof Promise) { | |
return PROMISE_OBJECT_TO_STRING; | |
} | |
return originalObjectToString.apply(this, arguments); | |
}; | |
}); | |
/** | |
* @license | |
* Copyright Google Inc. All Rights Reserved. | |
* | |
* Use of this source code is governed by an MIT-style license that can be | |
* found in the LICENSE file at https://angular.io/license | |
*/ | |
/** | |
* @fileoverview | |
* @suppress {missingRequire} | |
*/ | |
var passiveSupported = false; | |
if (typeof window !== 'undefined') { | |
try { | |
var options = Object.defineProperty({}, 'passive', { | |
get: function () { | |
passiveSupported = true; | |
} | |
}); | |
window.addEventListener('test', options, options); | |
window.removeEventListener('test', options, options); | |
} | |
catch (err) { | |
passiveSupported = false; | |
} | |
} | |
// an identifier to tell ZoneTask do not create a new invoke closure | |
var OPTIMIZED_ZONE_EVENT_TASK_DATA = { | |
useG: true | |
}; | |
var zoneSymbolEventNames$1 = {}; | |
var globalSources = {}; | |
var EVENT_NAME_SYMBOL_REGX = /^__zone_symbol__(\w+)(true|false)$/; | |
var IMMEDIATE_PROPAGATION_SYMBOL = ('__zone_symbol__propagationStopped'); | |
function patchEventTarget(_global, apis, patchOptions) { | |
var ADD_EVENT_LISTENER = (patchOptions && patchOptions.add) || ADD_EVENT_LISTENER_STR; | |
var REMOVE_EVENT_LISTENER = (patchOptions && patchOptions.rm) || REMOVE_EVENT_LISTENER_STR; | |
var LISTENERS_EVENT_LISTENER = (patchOptions && patchOptions.listeners) || 'eventListeners'; | |
var REMOVE_ALL_LISTENERS_EVENT_LISTENER = (patchOptions && patchOptions.rmAll) || 'removeAllListeners'; | |
var zoneSymbolAddEventListener = zoneSymbol(ADD_EVENT_LISTENER); | |
var ADD_EVENT_LISTENER_SOURCE = '.' + ADD_EVENT_LISTENER + ':'; | |
var PREPEND_EVENT_LISTENER = 'prependListener'; | |
var PREPEND_EVENT_LISTENER_SOURCE = '.' + PREPEND_EVENT_LISTENER + ':'; | |
var invokeTask = function (task, target, event) { | |
// for better performance, check isRemoved which is set | |
// by removeEventListener | |
if (task.isRemoved) { | |
return; | |
} | |
var delegate = task.callback; | |
if (typeof delegate === 'object' && delegate.handleEvent) { | |
// create the bind version of handleEvent when invoke | |
task.callback = function (event) { return delegate.handleEvent(event); }; | |
task.originalDelegate = delegate; | |
} | |
// invoke static task.invoke | |
task.invoke(task, target, [event]); | |
var options = task.options; | |
if (options && typeof options === 'object' && options.once) { | |
// if options.once is true, after invoke once remove listener here | |
// only browser need to do this, nodejs eventEmitter will cal removeListener | |
// inside EventEmitter.once | |
var delegate_1 = task.originalDelegate ? task.originalDelegate : task.callback; | |
target[REMOVE_EVENT_LISTENER].call(target, event.type, delegate_1, options); | |
} | |
}; | |
// global shared zoneAwareCallback to handle all event callback with capture = false | |
var globalZoneAwareCallback = function (event) { | |
// https://github.com/angular/zone.js/issues/911, in IE, sometimes | |
// event will be undefined, so we need to use window.event | |
event = event || _global.event; | |
if (!event) { | |
return; | |
} | |
// event.target is needed for Samsung TV and SourceBuffer | |
// || global is needed https://github.com/angular/zone.js/issues/190 | |
var target = this || event.target || _global; | |
var tasks = target[zoneSymbolEventNames$1[event.type][FALSE_STR]]; | |
if (tasks) { | |
// invoke all tasks which attached to current target with given event.type and capture = false | |
// for performance concern, if task.length === 1, just invoke | |
if (tasks.length === 1) { | |
invokeTask(tasks[0], target, event); | |
} | |
else { | |
// https://github.com/angular/zone.js/issues/836 | |
// copy the tasks array before invoke, to avoid | |
// the callback will remove itself or other listener | |
var copyTasks = tasks.slice(); | |
for (var i = 0; i < copyTasks.length; i++) { | |
if (event && event[IMMEDIATE_PROPAGATION_SYMBOL] === true) { | |
break; | |
} | |
invokeTask(copyTasks[i], target, event); | |
} | |
} | |
} | |
}; | |
// global shared zoneAwareCallback to handle all event callback with capture = true | |
var globalZoneAwareCaptureCallback = function (event) { | |
// https://github.com/angular/zone.js/issues/911, in IE, sometimes | |
// event will be undefined, so we need to use window.event | |
event = event || _global.event; | |
if (!event) { | |
return; | |
} | |
// event.target is needed for Samsung TV and SourceBuffer | |
// || global is needed https://github.com/angular/zone.js/issues/190 | |
var target = this || event.target || _global; | |
var tasks = target[zoneSymbolEventNames$1[event.type][TRUE_STR]]; | |
if (tasks) { | |
// invoke all tasks which attached to current target with given event.type and capture = false | |
// for performance concern, if task.length === 1, just invoke | |
if (tasks.length === 1) { | |
invokeTask(tasks[0], target, event); | |
} | |
else { | |
// https://github.com/angular/zone.js/issues/836 | |
// copy the tasks array before invoke, to avoid | |
// the callback will remove itself or other listener | |
var copyTasks = tasks.slice(); | |
for (var i = 0; i < copyTasks.length; i++) { | |
if (event && event[IMMEDIATE_PROPAGATION_SYMBOL] === true) { | |
break; | |
} | |
invokeTask(copyTasks[i], target, event); | |
} | |
} | |
} | |
}; | |
function patchEventTargetMethods(obj, patchOptions) { | |
if (!obj) { | |
return false; | |
} | |
var useGlobalCallback = true; | |
if (patchOptions && patchOptions.useG !== undefined) { | |
useGlobalCallback = patchOptions.useG; | |
} | |
var validateHandler = patchOptions && patchOptions.vh; | |
var checkDuplicate = true; | |
if (patchOptions && patchOptions.chkDup !== undefined) { | |
checkDuplicate = patchOptions.chkDup; | |
} | |
var returnTarget = false; | |
if (patchOptions && patchOptions.rt !== undefined) { | |
returnTarget = patchOptions.rt; | |
} | |
var proto = obj; | |
while (proto && !proto.hasOwnProperty(ADD_EVENT_LISTENER)) { | |
proto = ObjectGetPrototypeOf(proto); | |
} | |
if (!proto && obj[ADD_EVENT_LISTENER]) { | |
// somehow we did not find it, but we can see it. This happens on IE for Window properties. | |
proto = obj; | |
} | |
if (!proto) { | |
return false; | |
} | |
if (proto[zoneSymbolAddEventListener]) { | |
return false; | |
} | |
// a shared global taskData to pass data for scheduleEventTask | |
// so we do not need to create a new object just for pass some data | |
var taskData = {}; | |
var nativeAddEventListener = proto[zoneSymbolAddEventListener] = proto[ADD_EVENT_LISTENER]; | |
var nativeRemoveEventListener = proto[zoneSymbol(REMOVE_EVENT_LISTENER)] = | |
proto[REMOVE_EVENT_LISTENER]; | |
var nativeListeners = proto[zoneSymbol(LISTENERS_EVENT_LISTENER)] = | |
proto[LISTENERS_EVENT_LISTENER]; | |
var nativeRemoveAllListeners = proto[zoneSymbol(REMOVE_ALL_LISTENERS_EVENT_LISTENER)] = | |
proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER]; | |
var nativePrependEventListener; | |
if (patchOptions && patchOptions.prepend) { | |
nativePrependEventListener = proto[zoneSymbol(patchOptions.prepend)] = | |
proto[patchOptions.prepend]; | |
} | |
function checkIsPassive(task) { | |
if (!passiveSupported && typeof taskData.options !== 'boolean' && | |
typeof taskData.options !== 'undefined' && taskData.options !== null) { | |
// options is a non-null non-undefined object | |
// passive is not supported | |
// don't pass options as object | |
// just pass capture as a boolean | |
task.options = !!taskData.options.capture; | |
taskData.options = task.options; | |
} | |
} | |
var customScheduleGlobal = function (task) { | |
// if there is already a task for the eventName + capture, | |
// just return, because we use the shared globalZoneAwareCallback here. | |
if (taskData.isExisting) { | |
return; | |
} | |
checkIsPassive(task); | |
return nativeAddEventListener.call(taskData.target, taskData.eventName, taskData.capture ? globalZoneAwareCaptureCallback : globalZoneAwareCallback, taskData.options); | |
}; | |
var customCancelGlobal = function (task) { | |
// if task is not marked as isRemoved, this call is directly | |
// from Zone.prototype.cancelTask, we should remove the task | |
// from tasksList of target first | |
if (!task.isRemoved) { | |
var symbolEventNames = zoneSymbolEventNames$1[task.eventName]; | |
var symbolEventName = void 0; | |
if (symbolEventNames) { | |
symbolEventName = symbolEventNames[task.capture ? TRUE_STR : FALSE_STR]; | |
} | |
var existingTasks = symbolEventName && task.target[symbolEventName]; | |
if (existingTasks) { | |
for (var i = 0; i < existingTasks.length; i++) { | |
var existingTask = existingTasks[i]; | |
if (existingTask === task) { | |
existingTasks.splice(i, 1); | |
// set isRemoved to data for faster invokeTask check | |
task.isRemoved = true; | |
if (existingTasks.length === 0) { | |
// all tasks for the eventName + capture have gone, | |
// remove globalZoneAwareCallback and remove the task cache from target | |
task.allRemoved = true; | |
task.target[symbolEventName] = null; | |
} | |
break; | |
} | |
} | |
} | |
} | |
// if all tasks for the eventName + capture have gone, | |
// we will really remove the global event callback, | |
// if not, return | |
if (!task.allRemoved) { | |
return; | |
} | |
return nativeRemoveEventListener.call(task.target, task.eventName, task.capture ? globalZoneAwareCaptureCallback : globalZoneAwareCallback, task.options); | |
}; | |
var customScheduleNonGlobal = function (task) { | |
checkIsPassive(task); | |
return nativeAddEventListener.call(taskData.target, taskData.eventName, task.invoke, taskData.options); | |
}; | |
var customSchedulePrepend = function (task) { | |
return nativePrependEventListener.call(taskData.target, taskData.eventName, task.invoke, taskData.options); | |
}; | |
var customCancelNonGlobal = function (task) { | |
return nativeRemoveEventListener.call(task.target, task.eventName, task.invoke, task.options); | |
}; | |
var customSchedule = useGlobalCallback ? customScheduleGlobal : customScheduleNonGlobal; | |
var customCancel = useGlobalCallback ? customCancelGlobal : customCancelNonGlobal; | |
var compareTaskCallbackVsDelegate = function (task, delegate) { | |
var typeOfDelegate = typeof delegate; | |
return (typeOfDelegate === 'function' && task.callback === delegate) || | |
(typeOfDelegate === 'object' && task.originalDelegate === delegate); | |
}; | |
var compare = (patchOptions && patchOptions.diff) ? patchOptions.diff : compareTaskCallbackVsDelegate; | |
var blackListedEvents = Zone[Zone.__symbol__('BLACK_LISTED_EVENTS')]; | |
var makeAddListener = function (nativeListener, addSource, customScheduleFn, customCancelFn, returnTarget, prepend) { | |
if (returnTarget === void 0) { returnTarget = false; } | |
if (prepend === void 0) { prepend = false; } | |
return function () { | |
var target = this || _global; | |
var delegate = arguments[1]; | |
if (!delegate) { | |
return nativeListener.apply(this, arguments); | |
} | |
// don't create the bind delegate function for handleEvent | |
// case here to improve addEventListener performance | |
// we will create the bind delegate when invoke | |
var isHandleEvent = false; | |
if (typeof delegate !== 'function') { | |
if (!delegate.handleEvent) { | |
return nativeListener.apply(this, arguments); | |
} | |
isHandleEvent = true; | |
} | |
if (validateHandler && !validateHandler(nativeListener, delegate, target, arguments)) { | |
return; | |
} | |
var eventName = arguments[0]; | |
var options = arguments[2]; | |
if (blackListedEvents) { | |
// check black list | |
for (var i = 0; i < blackListedEvents.length; i++) { | |
if (eventName === blackListedEvents[i]) { | |
return nativeListener.apply(this, arguments); | |
} | |
} | |
} | |
var capture; | |
var once = false; | |
if (options === undefined) { | |
capture = false; | |
} | |
else if (options === true) { | |
capture = true; | |
} | |
else if (options === false) { | |
capture = false; | |
} | |
else { | |
capture = options ? !!options.capture : false; | |
once = options ? !!options.once : false; | |
} | |
var zone = Zone.current; | |
var symbolEventNames = zoneSymbolEventNames$1[eventName]; | |
var symbolEventName; | |
if (!symbolEventNames) { | |
// the code is duplicate, but I just want to get some better performance | |
var falseEventName = eventName + FALSE_STR; | |
var trueEventName = eventName + TRUE_STR; | |
var symbol = ZONE_SYMBOL_PREFIX + falseEventName; | |
var symbolCapture = ZONE_SYMBOL_PREFIX + trueEventName; | |
zoneSymbolEventNames$1[eventName] = {}; | |
zoneSymbolEventNames$1[eventName][FALSE_STR] = symbol; | |
zoneSymbolEventNames$1[eventName][TRUE_STR] = symbolCapture; | |
symbolEventName = capture ? symbolCapture : symbol; | |
} | |
else { | |
symbolEventName = symbolEventNames[capture ? TRUE_STR : FALSE_STR]; | |
} | |
var existingTasks = target[symbolEventName]; | |
var isExisting = false; | |
if (existingTasks) { | |
// already have task registered | |
isExisting = true; | |
if (checkDuplicate) { | |
for (var i = 0; i < existingTasks.length; i++) { | |
if (compare(existingTasks[i], delegate)) { | |
// same callback, same capture, same event name, just return | |
return; | |
} | |
} | |
} | |
} | |
else { | |
existingTasks = target[symbolEventName] = []; | |
} | |
var source; | |
var constructorName = target.constructor['name']; | |
var targetSource = globalSources[constructorName]; | |
if (targetSource) { | |
source = targetSource[eventName]; | |
} | |
if (!source) { | |
source = constructorName + addSource + eventName; | |
} | |
// do not create a new object as task.data to pass those things | |
// just use the global shared one | |
taskData.options = options; | |
if (once) { | |
// if addEventListener with once options, we don't pass it to | |
// native addEventListener, instead we keep the once setting | |
// and handle ourselves. | |
taskData.options.once = false; | |
} | |
taskData.target = target; | |
taskData.capture = capture; | |
taskData.eventName = eventName; | |
taskData.isExisting = isExisting; | |
var data = useGlobalCallback ? OPTIMIZED_ZONE_EVENT_TASK_DATA : undefined; | |
// keep taskData into data to allow onScheduleEventTask to access the task information | |
if (data) { | |
data.taskData = taskData; | |
} | |
var task = zone.scheduleEventTask(source, delegate, data, customScheduleFn, customCancelFn); | |
// should clear taskData.target to avoid memory leak | |
// issue, https://github.com/angular/angular/issues/20442 | |
taskData.target = null; | |
// need to clear up taskData because it is a global object | |
if (data) { | |
data.taskData = null; | |
} | |
// have to save those information to task in case | |
// application may call task.zone.cancelTask() directly | |
if (once) { | |
options.once = true; | |
} | |
if (!(!passiveSupported && typeof task.options === 'boolean')) { | |
// if not support passive, and we pass an option object | |
// to addEventListener, we should save the options to task | |
task.options = options; | |
} | |
task.target = target; | |
task.capture = capture; | |
task.eventName = eventName; | |
if (isHandleEvent) { | |
// save original delegate for compare to check duplicate | |
task.originalDelegate = delegate; | |
} | |
if (!prepend) { | |
existingTasks.push(task); | |
} | |
else { | |
existingTasks.unshift(task); | |
} | |
if (returnTarget) { | |
return target; | |
} | |
}; | |
}; | |
proto[ADD_EVENT_LISTENER] = makeAddListener(nativeAddEventListener, ADD_EVENT_LISTENER_SOURCE, customSchedule, customCancel, returnTarget); | |
if (nativePrependEventListener) { | |
proto[PREPEND_EVENT_LISTENER] = makeAddListener(nativePrependEventListener, PREPEND_EVENT_LISTENER_SOURCE, customSchedulePrepend, customCancel, returnTarget, true); | |
} | |
proto[REMOVE_EVENT_LISTENER] = function () { | |
var target = this || _global; | |
var eventName = arguments[0]; | |
var options = arguments[2]; | |
var capture; | |
if (options === undefined) { | |
capture = false; | |
} | |
else if (options === true) { | |
capture = true; | |
} | |
else if (options === false) { | |
capture = false; | |
} | |
else { | |
capture = options ? !!options.capture : false; | |
} | |
var delegate = arguments[1]; | |
if (!delegate) { | |
return nativeRemoveEventListener.apply(this, arguments); | |
} | |
if (validateHandler && | |
!validateHandler(nativeRemoveEventListener, delegate, target, arguments)) { | |
return; | |
} | |
var symbolEventNames = zoneSymbolEventNames$1[eventName]; | |
var symbolEventName; | |
if (symbolEventNames) { | |
symbolEventName = symbolEventNames[capture ? TRUE_STR : FALSE_STR]; | |
} | |
var existingTasks = symbolEventName && target[symbolEventName]; | |
if (existingTasks) { | |
for (var i = 0; i < existingTasks.length; i++) { | |
var existingTask = existingTasks[i]; | |
if (compare(existingTask, delegate)) { | |
existingTasks.splice(i, 1); | |
// set isRemoved to data for faster invokeTask check | |
existingTask.isRemoved = true; | |
if (existingTasks.length === 0) { | |
// all tasks for the eventName + capture have gone, | |
// remove globalZoneAwareCallback and remove the task cache from target | |
existingTask.allRemoved = true; | |
target[symbolEventName] = null; | |
} | |
existingTask.zone.cancelTask(existingTask); | |
if (returnTarget) { | |
return target; | |
} | |
return; | |
} | |
} | |
} | |
// issue 930, didn't find the event name or callback | |
// from zone kept existingTasks, the callback maybe | |
// added outside of zone, we need to call native removeEventListener | |
// to try to remove it. | |
return nativeRemoveEventListener.apply(this, arguments); | |
}; | |
proto[LISTENERS_EVENT_LISTENER] = function () { | |
var target = this || _global; | |
var eventName = arguments[0]; | |
var listeners = []; | |
var tasks = findEventTasks(target, eventName); | |
for (var i = 0; i < tasks.length; i++) { | |
var task = tasks[i]; | |
var delegate = task.originalDelegate ? task.originalDelegate : task.callback; | |
listeners.push(delegate); | |
} | |
return listeners; | |
}; | |
proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER] = function () { | |
var target = this || _global; | |
var eventName = arguments[0]; | |
if (!eventName) { | |
var keys = Object.keys(target); | |
for (var i = 0; i < keys.length; i++) { | |
var prop = keys[i]; | |
var match = EVENT_NAME_SYMBOL_REGX.exec(prop); | |
var evtName = match && match[1]; | |
// in nodejs EventEmitter, removeListener event is | |
// used for monitoring the removeListener call, | |
// so just keep removeListener eventListener until | |
// all other eventListeners are removed | |
if (evtName && evtName !== 'removeListener') { | |
this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].call(this, evtName); | |
} | |
} | |
// remove removeListener listener finally | |
this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].call(this, 'removeListener'); | |
} | |
else { | |
var symbolEventNames = zoneSymbolEventNames$1[eventName]; | |
if (symbolEventNames) { | |
var symbolEventName = symbolEventNames[FALSE_STR]; | |
var symbolCaptureEventName = symbolEventNames[TRUE_STR]; | |
var tasks = target[symbolEventName]; | |
var captureTasks = target[symbolCaptureEventName]; | |
if (tasks) { | |
var removeTasks = tasks.slice(); | |
for (var i = 0; i < removeTasks.length; i++) { | |
var task = removeTasks[i]; | |
var delegate = task.originalDelegate ? task.originalDelegate : task.callback; | |
this[REMOVE_EVENT_LISTENER].call(this, eventName, delegate, task.options); | |
} | |
} | |
if (captureTasks) { | |
var removeTasks = captureTasks.slice(); | |
for (var i = 0; i < removeTasks.length; i++) { | |
var task = removeTasks[i]; | |
var delegate = task.originalDelegate ? task.originalDelegate : task.callback; | |
this[REMOVE_EVENT_LISTENER].call(this, eventName, delegate, task.options); | |
} | |
} | |
} | |
} | |
if (returnTarget) { | |
return this; | |
} | |
}; | |
// for native toString patch | |
attachOriginToPatched(proto[ADD_EVENT_LISTENER], nativeAddEventListener); | |
attachOriginToPatched(proto[REMOVE_EVENT_LISTENER], nativeRemoveEventListener); | |
if (nativeRemoveAllListeners) { | |
attachOriginToPatched(proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER], nativeRemoveAllListeners); | |
} | |
if (nativeListeners) { | |
attachOriginToPatched(proto[LISTENERS_EVENT_LISTENER], nativeListeners); | |
} | |
return true; | |
} | |