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

Commit

Permalink
feat(core): add runOutsideOfZone ability
Browse files Browse the repository at this point in the history
  • Loading branch information
JiaLiPassion committed Sep 23, 2018
1 parent 31fc127 commit 68989db
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 23 deletions.
11 changes: 5 additions & 6 deletions lib/browser/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ Zone.__load_patch('XHR', (global: any, Zone: ZoneType) => {
task.invoke();
}
}
});
}, true);

const abortNative =
patchMethod(XMLHttpRequestPrototype, 'abort', () => function(self: any, args: any[]) {
Expand All @@ -244,13 +244,12 @@ Zone.__load_patch('XHR', (global: any, Zone: ZoneType) => {
return;
}
task.zone.cancelTask(task);
} else if ((Zone.current as any)[fetchTaskAborting] === true) {
// the abort is called from fetch polyfill, we need to call native abort of XHR.
return abortNative!.apply(self, args);
return;
}
// Otherwise, we are trying to abort an XHR which has not yet been sent, so there is no
// task
// to cancel. Do nothing.
// task to cancel. But we need to use abortNative to abort the XHR in case the send
// is called outside of Zone.
return abortNative!.apply(self, args);
});
}
});
Expand Down
2 changes: 1 addition & 1 deletion lib/browser/webapis-media-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Zone.__load_patch('mediaQuery', (global: any, Zone: ZoneType, api: _ZonePrivate)
} else {
return delegate.apply(self, args);
}
});
}, true);
}

function patchRemoveListener(proto: any) {
Expand Down
2 changes: 1 addition & 1 deletion lib/browser/webapis-resize-observer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Zone.__load_patch('ResizeObserver', (global: any, Zone: any, api: _ZonePrivate)
targets.push(target);
target[resizeObserverSymbol] = Zone.current;
return delegate.apply(self, args);
});
}, true);

api.patchMethod(
ResizeObserver.prototype, 'unobserve', (delegate: Function) => (self: any, args: any[]) => {
Expand Down
44 changes: 37 additions & 7 deletions lib/common/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,9 @@ export function patchEventTarget(
return function() {
const target = this || _global;
let delegate = arguments[1];
if (!delegate) {
// if handler is not available or we are in root zone
// use nativeListener
if (!delegate || Zone.current === Zone.root) {
return nativeListener.apply(this, arguments);
}

Expand Down Expand Up @@ -488,6 +490,10 @@ export function patchEventTarget(
}

proto[REMOVE_EVENT_LISTENER] = function() {
const delegate = arguments[1];
if (!delegate) {
return nativeRemoveEventListener.apply(this, arguments);
}
const target = this || _global;
const eventName = arguments[0];
const options = arguments[2];
Expand All @@ -503,11 +509,6 @@ export function patchEventTarget(
capture = options ? !!options.capture : false;
}

const delegate = arguments[1];
if (!delegate) {
return nativeRemoveEventListener.apply(this, arguments);
}

if (validateHandler &&
!validateHandler(nativeRemoveEventListener, delegate, target, arguments)) {
return;
Expand Down Expand Up @@ -553,11 +554,32 @@ export function patchEventTarget(

const listeners: any[] = [];
const tasks = findEventTasks(target, eventName);
const invokes: any[]|null = nativeListeners ? [] : null;

for (let i = 0; i < tasks.length; i++) {
const task: any = tasks[i];
let delegate = task.originalDelegate ? task.originalDelegate : task.callback;
listeners.push(delegate);
if (invokes) {
invokes.push(task.invoke);
}
}
if (nativeListeners) {
const natives = nativeListeners.apply(this, arguments);
if (natives && invokes) {
natives.forEach((n: any) => {
let found = false;
for (let i = 0; i < invokes.length; i++) {
if (invokes[i] === n) {
found = true;
break;
}
}
if (!found) {
listeners.push(n);
}
});
}
}
return listeners;
};
Expand All @@ -580,8 +602,12 @@ export function patchEventTarget(
this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].call(this, evtName);
}
}
// remove removeListener listener finally
// call native again in case some event handler was not
// use patched version of addListener
this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].call(this, 'removeListener');
if (nativeRemoveAllListeners) {
nativeRemoveAllListeners.call(this);
}
} else {
const symbolEventNames = zoneSymbolEventNames[eventName];
if (symbolEventNames) {
Expand Down Expand Up @@ -609,6 +635,10 @@ export function patchEventTarget(
}
}
}

if (nativeRemoveAllListeners) {
nativeRemoveAllListeners.call(this, eventName);
}
}

if (returnTarget) {
Expand Down
6 changes: 5 additions & 1 deletion lib/common/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ Zone.__load_patch('fetch', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
}
const placeholder = function() {};
global['fetch'] = function() {
// if in root zone, just use native fetch directly.
if (Zone.current === Zone.root) {
return fetch.apply(this, arguments);
}
const args = Array.prototype.slice.call(arguments);
const options = args.length > 1 ? args[1] : null;
const signal = options && options.signal;
Expand Down Expand Up @@ -97,4 +101,4 @@ Zone.__load_patch('fetch', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
}
});
};
});
});
2 changes: 1 addition & 1 deletion lib/common/timers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam
// cause an error by calling it directly.
return delegate.apply(window, args);
}
});
}, true);

clearNative =
patchMethod(window, cancelName, (delegate: Function) => function(self: any, args: any[]) {
Expand Down
11 changes: 8 additions & 3 deletions lib/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,8 @@ export function setShouldCopySymbolProperties(flag: boolean) {
export function patchMethod(
target: any, name: string,
patchFn: (delegate: Function, delegateName: string, name: string) => (self: any, args: any[]) =>
any): Function|null {
any,
checkInZone = false): Function|null {
let proto = target;
while (proto && !proto.hasOwnProperty(name)) {
proto = ObjectGetPrototypeOf(proto);
Expand All @@ -409,6 +410,10 @@ export function patchMethod(
if (isPropertyWritable(desc)) {
const patchDelegate = patchFn(delegate!, delegateName, name);
proto[name] = function() {
// if we are in root zone, just use native delegate.
if (checkInZone && Zone.current === Zone.root && delegate) {
return delegate.apply(this, arguments);
}
return patchDelegate(this, arguments as any);
};
attachOriginToPatched(proto[name], delegate);
Expand Down Expand Up @@ -449,7 +454,7 @@ export function patchMacroTask(
// cause an error by calling it directly.
return delegate.apply(self, args);
}
});
}, true);
}

export interface MicroTaskMeta extends TaskData {
Expand Down Expand Up @@ -480,7 +485,7 @@ export function patchMicroTask(
// cause an error by calling it directly.
return delegate.apply(self, args);
}
});
}, true);
}

export function attachOriginToPatched(patched: Function, original: any) {
Expand Down
10 changes: 7 additions & 3 deletions lib/zone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,8 @@ interface _ZonePrivate {
patchMethod:
(target: any, name: string,
patchFn: (delegate: Function, delegateName: string, name: string) =>
(self: any, args: any[]) => any) => Function | null;
(self: any, args: any[]) => any,
checkInZone?: boolean) => Function | null;
bindArguments: (args: any[], source: string) => any[];
}

Expand Down Expand Up @@ -710,7 +711,6 @@ const Zone: ZoneType = (function(global: any) {
return this._name;
}


private _parent: Zone|null;
private _name: string;
private _properties: {[key: string]: any};
Expand Down Expand Up @@ -752,6 +752,9 @@ const Zone: ZoneType = (function(global: any) {
const _callback = this._zoneDelegate.intercept(this, callback, source);
const zone: Zone = this;
return function() {
if (zone === rootZone) {
return _callback.apply(this, arguments);
}
return zone.runGuarded(_callback, (this as any), <any>arguments, source);
} as any as T;
}
Expand Down Expand Up @@ -1352,7 +1355,8 @@ const Zone: ZoneType = (function(global: any) {
}
},
};
let _currentZoneFrame: _ZoneFrame = {parent: null, zone: new Zone(null, null)};
const rootZone = new Zone(null, null);
let _currentZoneFrame: _ZoneFrame = {parent: null, zone: rootZone};
let _currentTask: Task|null = null;
let _numberOfNestedTaskFrames = 0;

Expand Down

0 comments on commit 68989db

Please sign in to comment.