build: move zone.js to angular repo (#30962)

PR Close #30962
This commit is contained in:
JiaLiPassion
2019-06-01 00:56:07 +09:00
committed by Kara Erickson
parent 7b3bcc23af
commit 5eb7426216
271 changed files with 30890 additions and 19 deletions

View File

@ -0,0 +1,99 @@
/**
* @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
*/
import '../zone-spec/async-test';
Zone.__load_patch('asynctest', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
/**
* Wraps a test function in an asynchronous test zone. The test will automatically
* complete when all asynchronous calls within this zone are done.
*/
(Zone as any)[api.symbol('asyncTest')] = function asyncTest(fn: Function): (done: any) => any {
// If we're running using the Jasmine test framework, adapt to call the 'done'
// function when asynchronous activity is finished.
if (global.jasmine) {
// Not using an arrow function to preserve context passed from call site
return function(done: any) {
if (!done) {
// if we run beforeEach in @angular/core/testing/testing_internal then we get no done
// fake it here and assume sync.
done = function() {};
done.fail = function(e: any) { throw e; };
}
runInTestZone(fn, this, done, (err: any) => {
if (typeof err === 'string') {
return done.fail(new Error(<string>err));
} else {
done.fail(err);
}
});
};
}
// Otherwise, return a promise which will resolve when asynchronous activity
// is finished. This will be correctly consumed by the Mocha framework with
// it('...', async(myFn)); or can be used in a custom framework.
// Not using an arrow function to preserve context passed from call site
return function() {
return new Promise<void>((finishCallback, failCallback) => {
runInTestZone(fn, this, finishCallback, failCallback);
});
};
};
function runInTestZone(
fn: Function, context: any, finishCallback: Function, failCallback: Function) {
const currentZone = Zone.current;
const AsyncTestZoneSpec = (Zone as any)['AsyncTestZoneSpec'];
if (AsyncTestZoneSpec === undefined) {
throw new Error(
'AsyncTestZoneSpec is needed for the async() test helper but could not be found. ' +
'Please make sure that your environment includes zone.js/dist/async-test.js');
}
const ProxyZoneSpec = (Zone as any)['ProxyZoneSpec'] as {
get(): {setDelegate(spec: ZoneSpec): void; getDelegate(): ZoneSpec;};
assertPresent: () => void;
};
if (ProxyZoneSpec === undefined) {
throw new Error(
'ProxyZoneSpec is needed for the async() test helper but could not be found. ' +
'Please make sure that your environment includes zone.js/dist/proxy.js');
}
const proxyZoneSpec = ProxyZoneSpec.get();
ProxyZoneSpec.assertPresent();
// We need to create the AsyncTestZoneSpec outside the ProxyZone.
// If we do it in ProxyZone then we will get to infinite recursion.
const proxyZone = Zone.current.getZoneWith('ProxyZoneSpec');
const previousDelegate = proxyZoneSpec.getDelegate();
proxyZone !.parent !.run(() => {
const testZoneSpec: ZoneSpec = new AsyncTestZoneSpec(
() => {
// Need to restore the original zone.
if (proxyZoneSpec.getDelegate() == testZoneSpec) {
// Only reset the zone spec if it's
// sill this one. Otherwise, assume
// it's OK.
proxyZoneSpec.setDelegate(previousDelegate);
}
(testZoneSpec as any).unPatchPromiseForTest();
currentZone.run(() => { finishCallback(); });
},
(error: any) => {
// Need to restore the original zone.
if (proxyZoneSpec.getDelegate() == testZoneSpec) {
// Only reset the zone spec if it's sill this one. Otherwise, assume it's OK.
proxyZoneSpec.setDelegate(previousDelegate);
}
(testZoneSpec as any).unPatchPromiseForTest();
currentZone.run(() => { failCallback(error); });
},
'test');
proxyZoneSpec.setDelegate(testZoneSpec);
(testZoneSpec as any).patchPromiseForTest();
});
return Zone.current.runGuarded(fn, context);
}
});

View File

@ -0,0 +1,153 @@
/**
* @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
*/
import '../zone-spec/fake-async-test';
Zone.__load_patch('fakeasync', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
const FakeAsyncTestZoneSpec = Zone && (Zone as any)['FakeAsyncTestZoneSpec'];
type ProxyZoneSpec = {
setDelegate(delegateSpec: ZoneSpec): void; getDelegate(): ZoneSpec; resetDelegate(): void;
};
const ProxyZoneSpec: {get(): ProxyZoneSpec; assertPresent: () => ProxyZoneSpec} =
Zone && (Zone as any)['ProxyZoneSpec'];
let _fakeAsyncTestZoneSpec: any = null;
/**
* Clears out the shared fake async zone for a test.
* To be called in a global `beforeEach`.
*
* @experimental
*/
function resetFakeAsyncZone() {
if (_fakeAsyncTestZoneSpec) {
_fakeAsyncTestZoneSpec.unlockDatePatch();
}
_fakeAsyncTestZoneSpec = null;
// in node.js testing we may not have ProxyZoneSpec in which case there is nothing to reset.
ProxyZoneSpec && ProxyZoneSpec.assertPresent().resetDelegate();
}
/**
* Wraps a function to be executed in the fakeAsync zone:
* - microtasks are manually executed by calling `flushMicrotasks()`,
* - timers are synchronous, `tick()` simulates the asynchronous passage of time.
*
* If there are any pending timers at the end of the function, an exception will be thrown.
*
* Can be used to wrap inject() calls.
*
* ## Example
*
* {@example core/testing/ts/fake_async.ts region='basic'}
*
* @param fn
* @returns The function wrapped to be executed in the fakeAsync zone
*
* @experimental
*/
function fakeAsync(fn: Function): (...args: any[]) => any {
// Not using an arrow function to preserve context passed from call site
return function(...args: any[]) {
const proxyZoneSpec = ProxyZoneSpec.assertPresent();
if (Zone.current.get('FakeAsyncTestZoneSpec')) {
throw new Error('fakeAsync() calls can not be nested');
}
try {
// in case jasmine.clock init a fakeAsyncTestZoneSpec
if (!_fakeAsyncTestZoneSpec) {
if (proxyZoneSpec.getDelegate() instanceof FakeAsyncTestZoneSpec) {
throw new Error('fakeAsync() calls can not be nested');
}
_fakeAsyncTestZoneSpec = new FakeAsyncTestZoneSpec();
}
let res: any;
const lastProxyZoneSpec = proxyZoneSpec.getDelegate();
proxyZoneSpec.setDelegate(_fakeAsyncTestZoneSpec);
_fakeAsyncTestZoneSpec.lockDatePatch();
try {
res = fn.apply(this, args);
flushMicrotasks();
} finally {
proxyZoneSpec.setDelegate(lastProxyZoneSpec);
}
if (_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length > 0) {
throw new Error(
`${_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length} ` +
`periodic timer(s) still in the queue.`);
}
if (_fakeAsyncTestZoneSpec.pendingTimers.length > 0) {
throw new Error(
`${_fakeAsyncTestZoneSpec.pendingTimers.length} timer(s) still in the queue.`);
}
return res;
} finally {
resetFakeAsyncZone();
}
};
}
function _getFakeAsyncZoneSpec(): any {
if (_fakeAsyncTestZoneSpec == null) {
_fakeAsyncTestZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec');
if (_fakeAsyncTestZoneSpec == null) {
throw new Error('The code should be running in the fakeAsync zone to call this function');
}
}
return _fakeAsyncTestZoneSpec;
}
/**
* Simulates the asynchronous passage of time for the timers in the fakeAsync zone.
*
* The microtasks queue is drained at the very start of this function and after any timer callback
* has been executed.
*
* ## Example
*
* {@example core/testing/ts/fake_async.ts region='basic'}
*
* @experimental
*/
function tick(millis: number = 0): void { _getFakeAsyncZoneSpec().tick(millis); }
/**
* Simulates the asynchronous passage of time for the timers in the fakeAsync zone by
* draining the macrotask queue until it is empty. The returned value is the milliseconds
* of time that would have been elapsed.
*
* @param maxTurns
* @returns The simulated time elapsed, in millis.
*
* @experimental
*/
function flush(maxTurns?: number): number { return _getFakeAsyncZoneSpec().flush(maxTurns); }
/**
* Discard all remaining periodic tasks.
*
* @experimental
*/
function discardPeriodicTasks(): void {
const zoneSpec = _getFakeAsyncZoneSpec();
const pendingTimers = zoneSpec.pendingPeriodicTimers;
zoneSpec.pendingPeriodicTimers.length = 0;
}
/**
* Flush any pending microtasks.
*
* @experimental
*/
function flushMicrotasks(): void { _getFakeAsyncZoneSpec().flushMicrotasks(); }
(Zone as any)[api.symbol('fakeAsyncTest')] = {
resetFakeAsyncZone, flushMicrotasks, discardPeriodicTasks, tick, flush, fakeAsync};
});

View File

@ -0,0 +1,68 @@
/**
* @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
*/
/**
* Promise for async/fakeAsync zoneSpec test
* can support async operation which not supported by zone.js
* such as
* it ('test jsonp in AsyncZone', async() => {
* new Promise(res => {
* jsonp(url, (data) => {
* // success callback
* res(data);
* });
* }).then((jsonpResult) => {
* // get jsonp result.
*
* // user will expect AsyncZoneSpec wait for
* // then, but because jsonp is not zone aware
* // AsyncZone will finish before then is called.
* });
* });
*/
Zone.__load_patch('promisefortest', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
const symbolState: string = api.symbol('state');
const UNRESOLVED: null = null;
const symbolParentUnresolved = api.symbol('parentUnresolved');
// patch Promise.prototype.then to keep an internal
// number for tracking unresolved chained promise
// we will decrease this number when the parent promise
// being resolved/rejected and chained promise was
// scheduled as a microTask.
// so we can know such kind of chained promise still
// not resolved in AsyncTestZone
(Promise as any)[api.symbol('patchPromiseForTest')] = function patchPromiseForTest() {
let oriThen = (Promise as any)[Zone.__symbol__('ZonePromiseThen')];
if (oriThen) {
return;
}
oriThen = (Promise as any)[Zone.__symbol__('ZonePromiseThen')] = Promise.prototype.then;
Promise.prototype.then = function() {
const chained = oriThen.apply(this, arguments);
if (this[symbolState] === UNRESOLVED) {
// parent promise is unresolved.
const asyncTestZoneSpec = Zone.current.get('AsyncTestZoneSpec');
if (asyncTestZoneSpec) {
asyncTestZoneSpec.unresolvedChainedPromiseCount++;
chained[symbolParentUnresolved] = true;
}
}
return chained;
};
};
(Promise as any)[api.symbol('unPatchPromiseForTest')] = function unpatchPromiseForTest() {
// restore origin then
const oriThen = (Promise as any)[Zone.__symbol__('ZonePromiseThen')];
if (oriThen) {
Promise.prototype.then = oriThen;
(Promise as any)[Zone.__symbol__('ZonePromiseThen')] = undefined;
}
};
});

View File

@ -0,0 +1,16 @@
/**
* @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
*/
// load test related files into bundle in correct order
import '../zone-spec/long-stack-trace';
import '../zone-spec/proxy';
import '../zone-spec/sync-test';
import '../jasmine/jasmine';
import './async-testing';
import './fake-async';
import './promise-testing';