perf(core): refactor NgZone, decrease size by 1.2Kb (#17773)
- Remove getters - Hide private methods for better property renaming ``` 497893 May 31 11:26 core.umd.js 718073 May 31 11:26 core.umd.js.map 217108 May 31 11:26 core.umd.min.js 575092 May 31 11:26 core.umd.min.js.map ``` ``` 495594 May 31 11:28 core.umd.js 716943 May 31 11:28 core.umd.js.map 215826 May 31 11:28 core.umd.min.js 574401 May 31 11:28 core.umd.min.js.map ``` diff: 1,282
This commit is contained in:
parent
d5dc53ead8
commit
b479ed9407
|
@ -84,18 +84,37 @@ import {EventEmitter} from '../event_emitter';
|
||||||
* @experimental
|
* @experimental
|
||||||
*/
|
*/
|
||||||
export class NgZone {
|
export class NgZone {
|
||||||
private outer: Zone;
|
readonly hasPendingMicrotasks: boolean = false;
|
||||||
private inner: Zone;
|
readonly hasPendingMacrotasks: boolean = false;
|
||||||
|
|
||||||
private _hasPendingMicrotasks: boolean = false;
|
/**
|
||||||
private _hasPendingMacrotasks: boolean = false;
|
* Whether there are no outstanding microtasks or macrotasks.
|
||||||
|
*/
|
||||||
|
readonly isStable: boolean = true;
|
||||||
|
|
||||||
private _isStable = true;
|
/**
|
||||||
private _nesting: number = 0;
|
* Notifies when code enters Angular Zone. This gets fired first on VM Turn.
|
||||||
private _onUnstable: EventEmitter<any> = new EventEmitter(false);
|
*/
|
||||||
private _onMicrotaskEmpty: EventEmitter<any> = new EventEmitter(false);
|
readonly onUnstable: EventEmitter<any> = new EventEmitter(false);
|
||||||
private _onStable: EventEmitter<any> = new EventEmitter(false);
|
|
||||||
private _onErrorEvents: EventEmitter<any> = new EventEmitter(false);
|
/**
|
||||||
|
* Notifies when there is no more microtasks enqueue in the current VM Turn.
|
||||||
|
* This is a hint for Angular to do change detection, which may enqueue more microtasks.
|
||||||
|
* For this reason this event can fire multiple times per VM Turn.
|
||||||
|
*/
|
||||||
|
readonly onMicrotaskEmpty: EventEmitter<any> = new EventEmitter(false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies when the last `onMicrotaskEmpty` has run and there are no more microtasks, which
|
||||||
|
* implies we are about to relinquish VM turn.
|
||||||
|
* This event gets called just once.
|
||||||
|
*/
|
||||||
|
readonly onStable: EventEmitter<any> = new EventEmitter(false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies that an error has been delivered.
|
||||||
|
*/
|
||||||
|
readonly onError: EventEmitter<any> = new EventEmitter(false);
|
||||||
|
|
||||||
constructor({enableLongStackTrace = false}) {
|
constructor({enableLongStackTrace = false}) {
|
||||||
if (typeof Zone == 'undefined') {
|
if (typeof Zone == 'undefined') {
|
||||||
|
@ -103,18 +122,20 @@ export class NgZone {
|
||||||
}
|
}
|
||||||
|
|
||||||
Zone.assertZonePatched();
|
Zone.assertZonePatched();
|
||||||
|
const self = this as any as NgZonePrivate;
|
||||||
|
self._nesting = 0;
|
||||||
|
|
||||||
this.outer = this.inner = Zone.current;
|
self._outer = self._inner = Zone.current;
|
||||||
|
|
||||||
if ((Zone as any)['wtfZoneSpec']) {
|
if ((Zone as any)['wtfZoneSpec']) {
|
||||||
this.inner = this.inner.fork((Zone as any)['wtfZoneSpec']);
|
self._inner = self._inner.fork((Zone as any)['wtfZoneSpec']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableLongStackTrace && (Zone as any)['longStackTraceZoneSpec']) {
|
if (enableLongStackTrace && (Zone as any)['longStackTraceZoneSpec']) {
|
||||||
this.inner = this.inner.fork((Zone as any)['longStackTraceZoneSpec']);
|
self._inner = self._inner.fork((Zone as any)['longStackTraceZoneSpec']);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.forkInnerZoneWithAngularBehavior();
|
forkInnerZoneWithAngularBehavior(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isInAngularZone(): boolean { return Zone.current.get('isAngularZone') === true; }
|
static isInAngularZone(): boolean { return Zone.current.get('isAngularZone') === true; }
|
||||||
|
@ -124,6 +145,7 @@ export class NgZone {
|
||||||
throw new Error('Expected to be in Angular Zone, but it is not!');
|
throw new Error('Expected to be in Angular Zone, but it is not!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static assertNotInAngularZone(): void {
|
static assertNotInAngularZone(): void {
|
||||||
if (NgZone.isInAngularZone()) {
|
if (NgZone.isInAngularZone()) {
|
||||||
throw new Error('Expected to not be in Angular Zone, but it is!');
|
throw new Error('Expected to not be in Angular Zone, but it is!');
|
||||||
|
@ -142,13 +164,13 @@ export class NgZone {
|
||||||
*
|
*
|
||||||
* If a synchronous error happens it will be rethrown and not reported via `onError`.
|
* If a synchronous error happens it will be rethrown and not reported via `onError`.
|
||||||
*/
|
*/
|
||||||
run(fn: () => any): any { return this.inner.run(fn); }
|
run(fn: () => any): any { return (this as any as NgZonePrivate)._inner.run(fn); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as `run`, except that synchronous errors are caught and forwarded via `onError` and not
|
* Same as `run`, except that synchronous errors are caught and forwarded via `onError` and not
|
||||||
* rethrown.
|
* rethrown.
|
||||||
*/
|
*/
|
||||||
runGuarded(fn: () => any): any { return this.inner.runGuarded(fn); }
|
runGuarded(fn: () => any): any { return (this as any as NgZonePrivate)._inner.runGuarded(fn); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the `fn` function synchronously in Angular's parent zone and returns value returned by
|
* Executes the `fn` function synchronously in Angular's parent zone and returns value returned by
|
||||||
|
@ -163,70 +185,48 @@ export class NgZone {
|
||||||
*
|
*
|
||||||
* Use {@link #run} to reenter the Angular zone and do work that updates the application model.
|
* Use {@link #run} to reenter the Angular zone and do work that updates the application model.
|
||||||
*/
|
*/
|
||||||
runOutsideAngular(fn: () => any): any { return this.outer.run(fn); }
|
runOutsideAngular(fn: () => any): any { return (this as any as NgZonePrivate)._outer.run(fn); }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
interface NgZonePrivate extends NgZone {
|
||||||
* Notifies when code enters Angular Zone. This gets fired first on VM Turn.
|
_outer: Zone;
|
||||||
*/
|
_inner: Zone;
|
||||||
get onUnstable(): EventEmitter<any> { return this._onUnstable; }
|
_nesting: number;
|
||||||
|
|
||||||
/**
|
hasPendingMicrotasks: boolean;
|
||||||
* Notifies when there is no more microtasks enqueue in the current VM Turn.
|
hasPendingMacrotasks: boolean;
|
||||||
* This is a hint for Angular to do change detection, which may enqueue more microtasks.
|
isStable: boolean;
|
||||||
* For this reason this event can fire multiple times per VM Turn.
|
}
|
||||||
*/
|
|
||||||
get onMicrotaskEmpty(): EventEmitter<any> { return this._onMicrotaskEmpty; }
|
|
||||||
|
|
||||||
/**
|
function checkStable(zone: NgZonePrivate) {
|
||||||
* Notifies when the last `onMicrotaskEmpty` has run and there are no more microtasks, which
|
if (zone._nesting == 0 && !zone.hasPendingMicrotasks && !zone.isStable) {
|
||||||
* implies we are about to relinquish VM turn.
|
|
||||||
* This event gets called just once.
|
|
||||||
*/
|
|
||||||
get onStable(): EventEmitter<any> { return this._onStable; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify that an error has been delivered.
|
|
||||||
*/
|
|
||||||
get onError(): EventEmitter<any> { return this._onErrorEvents; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether there are no outstanding microtasks or macrotasks.
|
|
||||||
*/
|
|
||||||
get isStable(): boolean { return this._isStable; }
|
|
||||||
|
|
||||||
get hasPendingMicrotasks(): boolean { return this._hasPendingMicrotasks; }
|
|
||||||
|
|
||||||
get hasPendingMacrotasks(): boolean { return this._hasPendingMacrotasks; }
|
|
||||||
|
|
||||||
private checkStable() {
|
|
||||||
if (this._nesting == 0 && !this._hasPendingMicrotasks && !this._isStable) {
|
|
||||||
try {
|
try {
|
||||||
this._nesting++;
|
zone._nesting++;
|
||||||
this._onMicrotaskEmpty.emit(null);
|
zone.onMicrotaskEmpty.emit(null);
|
||||||
} finally {
|
} finally {
|
||||||
this._nesting--;
|
zone._nesting--;
|
||||||
if (!this._hasPendingMicrotasks) {
|
if (!zone.hasPendingMicrotasks) {
|
||||||
try {
|
try {
|
||||||
this.runOutsideAngular(() => this._onStable.emit(null));
|
zone.runOutsideAngular(() => zone.onStable.emit(null));
|
||||||
} finally {
|
} finally {
|
||||||
this._isStable = true;
|
zone.isStable = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private forkInnerZoneWithAngularBehavior() {
|
function forkInnerZoneWithAngularBehavior(zone: NgZonePrivate) {
|
||||||
this.inner = this.inner.fork({
|
zone._inner = zone._inner.fork({
|
||||||
name: 'angular',
|
name: 'angular',
|
||||||
properties: <any>{'isAngularZone': true},
|
properties: <any>{'isAngularZone': true},
|
||||||
onInvokeTask: (delegate: ZoneDelegate, current: Zone, target: Zone, task: Task,
|
onInvokeTask: (delegate: ZoneDelegate, current: Zone, target: Zone, task: Task, applyThis: any,
|
||||||
applyThis: any, applyArgs: any): any => {
|
applyArgs: any): any => {
|
||||||
try {
|
try {
|
||||||
this.onEnter();
|
onEnter(zone);
|
||||||
return delegate.invokeTask(target, task, applyThis, applyArgs);
|
return delegate.invokeTask(target, task, applyThis, applyArgs);
|
||||||
} finally {
|
} finally {
|
||||||
this.onLeave();
|
onLeave(zone);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -234,10 +234,10 @@ export class NgZone {
|
||||||
onInvoke: (delegate: ZoneDelegate, current: Zone, target: Zone, callback: Function,
|
onInvoke: (delegate: ZoneDelegate, current: Zone, target: Zone, callback: Function,
|
||||||
applyThis: any, applyArgs: any[], source: string): any => {
|
applyThis: any, applyArgs: any[], source: string): any => {
|
||||||
try {
|
try {
|
||||||
this.onEnter();
|
onEnter(zone);
|
||||||
return delegate.invoke(target, callback, applyThis, applyArgs, source);
|
return delegate.invoke(target, callback, applyThis, applyArgs, source);
|
||||||
} finally {
|
} finally {
|
||||||
this.onLeave();
|
onLeave(zone);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -248,40 +248,31 @@ export class NgZone {
|
||||||
// We are only interested in hasTask events which originate from our zone
|
// We are only interested in hasTask events which originate from our zone
|
||||||
// (A child hasTask event is not interesting to us)
|
// (A child hasTask event is not interesting to us)
|
||||||
if (hasTaskState.change == 'microTask') {
|
if (hasTaskState.change == 'microTask') {
|
||||||
this.setHasMicrotask(hasTaskState.microTask);
|
zone.hasPendingMicrotasks = hasTaskState.microTask;
|
||||||
|
checkStable(zone);
|
||||||
} else if (hasTaskState.change == 'macroTask') {
|
} else if (hasTaskState.change == 'macroTask') {
|
||||||
this.setHasMacrotask(hasTaskState.macroTask);
|
zone.hasPendingMacrotasks = hasTaskState.macroTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onHandleError: (delegate: ZoneDelegate, current: Zone, target: Zone, error: any): boolean => {
|
onHandleError: (delegate: ZoneDelegate, current: Zone, target: Zone, error: any): boolean => {
|
||||||
delegate.handleError(target, error);
|
delegate.handleError(target, error);
|
||||||
this.triggerError(error);
|
zone.onError.emit(error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private onEnter() {
|
function onEnter(zone: NgZonePrivate) {
|
||||||
this._nesting++;
|
zone._nesting++;
|
||||||
if (this._isStable) {
|
if (zone.isStable) {
|
||||||
this._isStable = false;
|
zone.isStable = false;
|
||||||
this._onUnstable.emit(null);
|
zone.onUnstable.emit(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onLeave() {
|
function onLeave(zone: NgZonePrivate) {
|
||||||
this._nesting--;
|
zone._nesting--;
|
||||||
this.checkStable();
|
checkStable(zone);
|
||||||
}
|
|
||||||
|
|
||||||
private setHasMicrotask(hasMicrotasks: boolean) {
|
|
||||||
this._hasPendingMicrotasks = hasMicrotasks;
|
|
||||||
this.checkStable();
|
|
||||||
}
|
|
||||||
|
|
||||||
private setHasMacrotask(hasMacrotasks: boolean) { this._hasPendingMacrotasks = hasMacrotasks; }
|
|
||||||
|
|
||||||
private triggerError(error: any) { this._onErrorEvents.emit(error); }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,22 +28,20 @@ function microTask(fn: Function): void {
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class MockNgZone extends NgZone {
|
class MockNgZone extends NgZone {
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_onUnstableStream: EventEmitter<any>;
|
onUnstable: EventEmitter<any>;
|
||||||
get onUnstable() { return this._onUnstableStream; }
|
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_onStableStream: EventEmitter<any>;
|
onStable: EventEmitter<any>;
|
||||||
get onStable() { return this._onStableStream; }
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super({enableLongStackTrace: false});
|
super({enableLongStackTrace: false});
|
||||||
this._onUnstableStream = new EventEmitter(false);
|
this.onUnstable = new EventEmitter(false);
|
||||||
this._onStableStream = new EventEmitter(false);
|
this.onStable = new EventEmitter(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
unstable(): void { this._onUnstableStream.emit(null); }
|
unstable(): void { this.onUnstable.emit(null); }
|
||||||
|
|
||||||
stable(): void { this._onStableStream.emit(null); }
|
stable(): void { this.onStable.emit(null); }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
|
|
|
@ -14,12 +14,10 @@ import {EventEmitter, Injectable, NgZone} from '@angular/core';
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MockNgZone extends NgZone {
|
export class MockNgZone extends NgZone {
|
||||||
private _mockOnStable: EventEmitter<any> = new EventEmitter(false);
|
onStable: EventEmitter<any> = new EventEmitter(false);
|
||||||
|
|
||||||
constructor() { super({enableLongStackTrace: false}); }
|
constructor() { super({enableLongStackTrace: false}); }
|
||||||
|
|
||||||
get onStable() { return this._mockOnStable; }
|
|
||||||
|
|
||||||
run(fn: Function): any { return fn(); }
|
run(fn: Function): any { return fn(); }
|
||||||
|
|
||||||
runOutsideAngular(fn: Function): any { return fn(); }
|
runOutsideAngular(fn: Function): any { return fn(); }
|
||||||
|
|
Loading…
Reference in New Issue