refactor: ensure zone.js can be built with typescript strict flag (#30993)

As part of FW-1265, the `zone.js` package is made compatible
with the TypeScript `--strict` flag. Read more about the strict flag [here](https://www.typescriptlang.org/docs/handbook/compiler-options.html)

PR Close #30993
This commit is contained in:
Paul Gschwendtner 2019-06-26 10:33:02 +02:00 committed by Miško Hevery
parent 10a1e1974b
commit 60f58bf051
20 changed files with 77 additions and 66 deletions

View File

@ -7,7 +7,7 @@
*/
Zone.__load_patch('getUserMedia', (global: any, Zone: any, api: _ZonePrivate) => {
function wrapFunctionArgs(func: Function, source?: string): Function {
return function() {
return function(this: unknown) {
const args = Array.prototype.slice.call(arguments);
const wrappedArgs = api.bindArguments(args, source ? source : (func as any).name);
return func.apply(this, wrappedArgs);

View File

@ -115,7 +115,7 @@ Zone.__load_patch('Error', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
* This is ZoneAwareError which processes the stack frame and cleans up extra frames as well as
* adds zone information to it.
*/
function ZoneAwareError(): Error {
function ZoneAwareError(this: unknown | typeof NativeError): Error {
// We always have to return native error otherwise the browser console will not work.
let error: Error = NativeError.apply(this, arguments);
// Save original stack trace

View File

@ -112,7 +112,7 @@ export function patchEventTarget(
};
// global shared zoneAwareCallback to handle all event callback with capture = false
const globalZoneAwareCallback = function(event: Event) {
const globalZoneAwareCallback = function(this: unknown, event: 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;
@ -144,7 +144,7 @@ export function patchEventTarget(
};
// global shared zoneAwareCallback to handle all event callback with capture = true
const globalZoneAwareCaptureCallback = function(event: Event) {
const globalZoneAwareCaptureCallback = function(this: unknown, event: 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;
@ -330,7 +330,7 @@ export function patchEventTarget(
const makeAddListener = function(
nativeListener: any, addSource: string, customScheduleFn: any, customCancelFn: any,
returnTarget = false, prepend = false) {
return function() {
return function(this: unknown) {
const target = this || _global;
const eventName = arguments[0];
let delegate = arguments[1];

View File

@ -54,7 +54,7 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr
const UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL = __symbol__('unhandledPromiseRejectionHandler');
function handleUnhandledRejection(e: any) {
function handleUnhandledRejection(this: unknown, e: any) {
api.onUnhandledError(e);
try {
const handler = (Zone as any)[UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL];
@ -198,7 +198,7 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr
}
const REJECTION_HANDLED_HANDLER = __symbol__('rejectionHandledHandler');
function clearRejectedNoCatch(promise: ZoneAwarePromise<any>): void {
function clearRejectedNoCatch(this: unknown, promise: ZoneAwarePromise<any>): void {
if ((promise as any)[symbolState] === REJECTED_NO_CATCH) {
// if the promise is rejected no catch status
// and queue.length > 0, means there is a error handler
@ -453,7 +453,7 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr
api.patchThen = patchThen;
function zoneify(fn: Function) {
return function() {
return function(this: unknown) {
let resultPromise = fn.apply(this, arguments);
if (resultPromise instanceof ZoneAwarePromise) {
return resultPromise;

View File

@ -29,7 +29,7 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam
function scheduleTask(task: Task) {
const data = <TimerOptions>task.data;
function timer() {
function timer(this: unknown) {
try {
task.invoke.apply(this, arguments);
} finally {

View File

@ -16,9 +16,9 @@ Zone.__load_patch('toString', (global: any) => {
const ORIGINAL_DELEGATE_SYMBOL = zoneSymbol('OriginalDelegate');
const PROMISE_SYMBOL = zoneSymbol('Promise');
const ERROR_SYMBOL = zoneSymbol('Error');
const newFunctionToString = function toString() {
const newFunctionToString = function toString(this: unknown) {
if (typeof this === 'function') {
const originalDelegate = this[ORIGINAL_DELEGATE_SYMBOL];
const originalDelegate = (this as any)[ORIGINAL_DELEGATE_SYMBOL];
if (originalDelegate) {
if (typeof originalDelegate === 'function') {
return originalFunctionToString.call(originalDelegate);

View File

@ -80,7 +80,7 @@ export function patchPrototype(prototype: any, fnNames: string[]) {
continue;
}
prototype[name] = ((delegate: Function) => {
const patched: any = function() {
const patched: any = function(this: unknown) {
return delegate.apply(this, bindArguments(<any>arguments, source + '.' + name));
};
attachOriginToPatched(patched, delegate);
@ -123,7 +123,7 @@ export const isMix: boolean = typeof _global.process !== 'undefined' &&
const zoneSymbolEventNames: {[eventName: string]: string} = {};
const wrapFn = function(event: Event) {
const wrapFn = function(this: unknown, event: 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;
@ -197,7 +197,7 @@ export function patchProperty(obj: any, prop: string, prototype?: any) {
eventNameSymbol = zoneSymbolEventNames[eventName] = zoneSymbol('ON_PROPERTY' + eventName);
}
desc.set = function(newValue) {
desc.set = function(this: EventSource, newValue) {
// in some of windows's onproperty callback, this is undefined
// so we need to check it
let target = this;
@ -207,7 +207,7 @@ export function patchProperty(obj: any, prop: string, prototype?: any) {
if (!target) {
return;
}
let previousValue = target[eventNameSymbol];
let previousValue = (target as any)[eventNameSymbol];
if (previousValue) {
target.removeEventListener(eventName, wrapFn);
}
@ -219,10 +219,10 @@ export function patchProperty(obj: any, prop: string, prototype?: any) {
}
if (typeof newValue === 'function') {
target[eventNameSymbol] = newValue;
(target as any)[eventNameSymbol] = newValue;
target.addEventListener(eventName, wrapFn, false);
} else {
target[eventNameSymbol] = null;
(target as any)[eventNameSymbol] = null;
}
};
@ -238,7 +238,7 @@ export function patchProperty(obj: any, prop: string, prototype?: any) {
if (!target) {
return null;
}
const listener = target[eventNameSymbol];
const listener = (target as any)[eventNameSymbol];
if (listener) {
return listener;
} else if (originalDescGet) {
@ -251,8 +251,8 @@ export function patchProperty(obj: any, prop: string, prototype?: any) {
let value = originalDescGet && originalDescGet.call(this);
if (value) {
desc !.set !.call(this, value);
if (typeof target[REMOVE_ATTRIBUTE] === 'function') {
target.removeAttribute(prop);
if (typeof(target as any)[REMOVE_ATTRIBUTE] === 'function') {
(target as any).removeAttribute(prop);
}
return value;
}

View File

@ -42,7 +42,7 @@ Zone.__load_patch('jsonp', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
configurable: true,
enumerable: true,
get: function() {
return function() {
return function(this: unknown) {
const task = global[api.symbol('jsonpTask')];
const target = this ? this : global;
const delegate = global[api.symbol(`jsonp${methodName}callback`)];

View File

@ -13,7 +13,7 @@
const __extends = function(d: any, b: any) {
for (const p in b)
if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
function __(this: Object) { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : ((__.prototype = b.prototype), new (__ as any)());
};
// Patch jasmine's describe/it/beforeEach/afterEach functions so test code always runs
@ -149,13 +149,16 @@
* synchronous-only zone.
*/
function wrapDescribeInZone(describeBody: Function): Function {
return function() { return syncZone.run(describeBody, this, (arguments as any) as any[]); };
return function(this: unknown) {
return syncZone.run(describeBody, this, (arguments as any) as any[]);
};
}
function runInTestZone(testBody: Function, applyThis: any, queueRunner: any, done?: Function) {
function runInTestZone(
testBody: Function, applyThis: any, queueRunner: QueueRunner, done?: Function) {
const isClockInstalled = !!(jasmine as any)[symbol('clockInstalled')];
const testProxyZoneSpec = queueRunner.testProxyZoneSpec;
const testProxyZone = queueRunner.testProxyZone;
const testProxyZoneSpec = queueRunner.testProxyZoneSpec !;
const testProxyZone = queueRunner.testProxyZone !;
let lastDelegate;
if (isClockInstalled && enableAutoFakeAsyncWhenClockPatched) {
// auto run a fakeAsync
@ -180,12 +183,16 @@
// The `done` callback is only passed through if the function expects at least one argument.
// Note we have to make a function with correct number of arguments, otherwise jasmine will
// think that all functions are sync or async.
return (testBody && (testBody.length ? function(done: Function) {
return runInTestZone(testBody, this, this.queueRunner, done);
} : function() { return runInTestZone(testBody, this, this.queueRunner); }));
return (testBody && (testBody.length ? function(this: QueueRunnerUserContext, done: Function) {
return runInTestZone(testBody, this, this.queueRunner !, done);
} : function(this: QueueRunnerUserContext) {
return runInTestZone(testBody, this, this.queueRunner !);
}));
}
interface QueueRunner {
execute(): void;
testProxyZoneSpec: ZoneSpec|null;
testProxyZone: Zone|null;
}
interface QueueRunnerAttrs {
queueableFns: {fn: Function}[];
@ -194,16 +201,16 @@
fail: () => void;
onComplete: () => void;
onException: (error: any) => void;
userContext: any;
userContext: QueueRunnerUserContext;
timeout: {setTimeout: Function; clearTimeout: Function};
}
type QueueRunnerUserContext = {queueRunner?: QueueRunner};
const QueueRunner = (jasmine as any).QueueRunner as {
new (attrs: QueueRunnerAttrs): QueueRunner;
};
(jasmine as any).QueueRunner = (function(_super) {
__extends(ZoneQueueRunner, _super);
function ZoneQueueRunner(attrs: QueueRunnerAttrs) {
function ZoneQueueRunner(this: QueueRunner, attrs: QueueRunnerAttrs) {
if (attrs.onComplete) {
attrs.onComplete = (fn => () => {
// All functions are done, clear the test zone.
@ -239,7 +246,7 @@
// patch attrs.onException
const onException = attrs.onException;
attrs.onException = function(error: any) {
attrs.onException = function(this: undefined|QueueRunner, error: any) {
if (error &&
error.message ===
'Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.') {

View File

@ -67,7 +67,7 @@
function wrapDescribeInZone(args: IArguments): any[] {
const syncTest: any = function(fn: Function) {
return function() { return syncZone.run(fn, this, arguments as any as any[]); };
return function(this: unknown) { return syncZone.run(fn, this, arguments as any as any[]); };
};
return modifyArguments(args, syncTest);
@ -75,11 +75,11 @@
function wrapTestInZone(args: IArguments): any[] {
const asyncTest = function(fn: Function) {
return function(done: Function) { return testZone !.run(fn, this, [done]); };
return function(this: unknown, done: Function) { return testZone !.run(fn, this, [done]); };
};
const syncTest: any = function(fn: Function) {
return function() { return testZone !.run(fn, this); };
return function(this: unknown) { return testZone !.run(fn, this); };
};
return modifyArguments(args, syncTest, asyncTest);
@ -87,11 +87,11 @@
function wrapSuiteInZone(args: IArguments): any[] {
const asyncTest = function(fn: Function) {
return function(done: Function) { return suiteZone.run(fn, this, [done]); };
return function(this: unknown, done: Function) { return suiteZone.run(fn, this, [done]); };
};
const syncTest: any = function(fn: Function) {
return function() { return suiteZone.run(fn, this); };
return function(this: unknown) { return suiteZone.run(fn, this); };
};
return modifyArguments(args, syncTest, asyncTest);

View File

@ -8,6 +8,10 @@
import {Observable, Subscriber, Subscription} from 'rxjs';
type ZoneSubscriberContext = {
_zone: Zone
} & Subscriber<any>;
(Zone as any).__load_patch('rxjs', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
const symbol: (symbolString: string) => string = (Zone as any).__symbol__;
const nextSource = 'rxjs.Subscriber.next';
@ -46,14 +50,14 @@ import {Observable, Subscriber, Subscription} from 'rxjs';
},
set: function(this: Observable<any>, subscribe: any) {
(this as any)._zone = Zone.current;
(this as any)._zoneSubscribe = function() {
(this as any)._zoneSubscribe = function(this: ZoneSubscriberContext) {
if (this._zone && this._zone !== Zone.current) {
const tearDown = this._zone.run(subscribe, this, arguments);
const tearDown = this._zone.run(subscribe, this, arguments as any);
if (tearDown && typeof tearDown === 'function') {
const zone = this._zone;
return function() {
return function(this: ZoneSubscriberContext) {
if (zone !== Zone.current) {
return zone.run(tearDown, this, arguments);
return zone.run(tearDown, this, arguments as any);
}
return tearDown.apply(this, arguments);
};
@ -136,40 +140,40 @@ import {Observable, Subscriber, Subscription} from 'rxjs';
// patch Subscriber.next to make sure it run
// into SubscriptionZone
Subscriber.prototype.next = function() {
Subscriber.prototype.next = function(this: ZoneSubscriberContext) {
const currentZone = Zone.current;
const subscriptionZone = this._zone;
// for performance concern, check Zone.current
// equal with this._zone(SubscriptionZone) or not
if (subscriptionZone && subscriptionZone !== currentZone) {
return subscriptionZone.run(next, this, arguments, nextSource);
return subscriptionZone.run(next, this, arguments as any, nextSource);
} else {
return next.apply(this, arguments as any);
}
};
Subscriber.prototype.error = function() {
Subscriber.prototype.error = function(this: ZoneSubscriberContext) {
const currentZone = Zone.current;
const subscriptionZone = this._zone;
// for performance concern, check Zone.current
// equal with this._zone(SubscriptionZone) or not
if (subscriptionZone && subscriptionZone !== currentZone) {
return subscriptionZone.run(error, this, arguments, errorSource);
return subscriptionZone.run(error, this, arguments as any, errorSource);
} else {
return error.apply(this, arguments as any);
}
};
Subscriber.prototype.complete = function() {
Subscriber.prototype.complete = function(this: ZoneSubscriberContext) {
const currentZone = Zone.current;
const subscriptionZone = this._zone;
// for performance concern, check Zone.current
// equal with this._zone(SubscriptionZone) or not
if (subscriptionZone && subscriptionZone !== currentZone) {
return subscriptionZone.run(complete, this, arguments, completeSource);
return subscriptionZone.run(complete, this, arguments as any, completeSource);
} else {
return complete.call(this);
}

View File

@ -17,7 +17,7 @@ Zone.__load_patch('asynctest', (global: any, Zone: ZoneType, api: _ZonePrivate)
// 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) {
return function(this: unknown, 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.
@ -37,7 +37,7 @@ Zone.__load_patch('asynctest', (global: any, Zone: ZoneType, api: _ZonePrivate)
// 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 function(this: unknown) {
return new Promise<void>((finishCallback, failCallback) => {
runInTestZone(fn, this, finishCallback, failCallback);
});
@ -96,4 +96,4 @@ Zone.__load_patch('asynctest', (global: any, Zone: ZoneType, api: _ZonePrivate)
});
return Zone.current.runGuarded(fn, context);
}
});
});

View File

@ -52,7 +52,7 @@ Zone.__load_patch('fakeasync', (global: any, Zone: ZoneType, api: _ZonePrivate)
*/
function fakeAsync(fn: Function): (...args: any[]) => any {
// Not using an arrow function to preserve context passed from call site
return function(...args: any[]) {
return function(this: unknown, ...args: any[]) {
const proxyZoneSpec = ProxyZoneSpec.assertPresent();
if (Zone.current.get('FakeAsyncTestZoneSpec')) {
throw new Error('fakeAsync() calls can not be nested');
@ -150,4 +150,4 @@ Zone.__load_patch('fakeasync', (global: any, Zone: ZoneType, api: _ZonePrivate)
function flushMicrotasks(): void { _getFakeAsyncZoneSpec().flushMicrotasks(); }
(Zone as any)[api.symbol('fakeAsyncTest')] = {
resetFakeAsyncZone, flushMicrotasks, discardPeriodicTasks, tick, flush, fakeAsync};
});
});

View File

@ -45,7 +45,7 @@ Zone.__load_patch('promisefortest', (global: any, Zone: ZoneType, api: _ZonePriv
oriThen = (Promise as any)[Zone.__symbol__('ZonePromiseThen')] = Promise.prototype.then;
Promise.prototype.then = function() {
const chained = oriThen.apply(this, arguments);
if (this[symbolState] === UNRESOLVED) {
if ((this as any)[symbolState] === UNRESOLVED) {
// parent promise is unresolved.
const asyncTestZoneSpec = Zone.current.get('AsyncTestZoneSpec');
if (asyncTestZoneSpec) {
@ -65,4 +65,4 @@ Zone.__load_patch('promisefortest', (global: any, Zone: ZoneType, api: _ZonePriv
(Promise as any)[Zone.__symbol__('ZonePromiseThen')] = undefined;
}
};
});
});

View File

@ -78,7 +78,9 @@ function renderLongStackTrace(frames: LongStackTrace[], stack?: string): string
return longTrace.join(NEWLINE);
}
(Zone as any)['longStackTraceZoneSpec'] = <ZoneSpec>{
type LongStackTraceZoneSpec = ZoneSpec & {longStackTraceLimit: number};
(Zone as any)['longStackTraceZoneSpec'] = <LongStackTraceZoneSpec>{
name: 'long-stack-trace',
longStackTraceLimit: 10, // Max number of task to keep the stack trace for.
// add a getLongStackTrace method in spec to

View File

@ -781,8 +781,8 @@ const Zone: ZoneType = (function(global: any) {
}
const _callback = this._zoneDelegate.intercept(this, callback, source);
const zone: Zone = this;
return function() {
return zone.runGuarded(_callback, (this as any), <any>arguments, source);
return function(this: unknown) {
return zone.runGuarded(_callback, this, <any>arguments, source);
} as any as T;
}

View File

@ -13,7 +13,8 @@ const detectTask = Zone.current.scheduleMacroTask('detectTask', noop, undefined,
const originalTransitionTo = detectTask.constructor.prototype._transitionTo;
// patch _transitionTo of ZoneTask to add log for test
const logTransitionTo: Function = function(
toState: TaskState, fromState1: TaskState, fromState2?: TaskState) {
this: Task&{_state: TaskState}, toState: TaskState, fromState1: TaskState,
fromState2?: TaskState) {
log.push({
zone: Zone.current.name,
taskZone: this.zone && this.zone.name,
@ -24,7 +25,7 @@ const logTransitionTo: Function = function(
};
function testFnWithLoggedTransitionTo(testFn: Function) {
return function() {
return function(this: unknown) {
detectTask.constructor.prototype._transitionTo = logTransitionTo;
testFn.apply(this, arguments);
detectTask.constructor.prototype._transitionTo = originalTransitionTo;

View File

@ -86,7 +86,7 @@ export function isSupportSetErrorStack() {
(isSupportSetErrorStack as any).message = 'supportSetErrorStack';
export function asyncTest(testFn: Function, zone: Zone = Zone.current) {
export function asyncTest(this: unknown, testFn: Function, zone: Zone = Zone.current) {
const AsyncTestZoneSpec = (Zone as any)['AsyncTestZoneSpec'];
return (done: Function) => {
let asyncTestZone: Zone =

View File

@ -247,9 +247,9 @@ describe('AsyncTestZoneSpec', function() {
const asyncTest: any = (Zone as any)[Zone.__symbol__('asyncTest')];
function wrapAsyncTest(fn: Function, doneFn?: Function) {
return function(done: Function) {
return function(this: unknown, done: Function) {
const asyncWrapper = asyncTest(fn);
return asyncWrapper.apply(this, [function() {
return asyncWrapper.apply(this, [function(this: unknown) {
if (doneFn) {
doneFn();
}

View File

@ -2,9 +2,6 @@
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": true,
"noImplicitReturns": false,
"noImplicitThis": false,
"outDir": "build",
"inlineSourceMap": true,
"inlineSources": true,