blob: 94ef7fb053e2d00ec7f271f8c1dbc3542f03a156 [file] [log] [blame]
/**
* @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 './node_util';
import './events';
import './fs';
import {findEventTasks} from '../common/events';
import {patchTimer} from '../common/timers';
import {ArraySlice, isMix, patchMacroTask, patchMicroTask} from '../common/utils';
const set = 'set';
const clear = 'clear';
Zone.__load_patch('node_timers', (global: any, Zone: ZoneType) => {
// Timers
let globalUseTimeoutFromTimer = false;
try {
const timers = require('timers');
let globalEqualTimersTimeout = global.setTimeout === timers.setTimeout;
if (!globalEqualTimersTimeout && !isMix) {
// 1. if isMix, then we are in mix environment such as Electron
// we should only patch timers.setTimeout because global.setTimeout
// have been patched
// 2. if global.setTimeout not equal timers.setTimeout, check
// whether global.setTimeout use timers.setTimeout or not
const originSetTimeout = timers.setTimeout;
timers.setTimeout = function() {
globalUseTimeoutFromTimer = true;
return originSetTimeout.apply(this, arguments);
};
const detectTimeout = global.setTimeout(() => {}, 100);
clearTimeout(detectTimeout);
timers.setTimeout = originSetTimeout;
}
patchTimer(timers, set, clear, 'Timeout');
patchTimer(timers, set, clear, 'Interval');
patchTimer(timers, set, clear, 'Immediate');
} catch (error) {
// timers module not exists, for example, when we using nativeScript
// timers is not available
}
if (isMix) {
// if we are in mix environment, such as Electron,
// the global.setTimeout has already been patched,
// so we just patch timers.setTimeout
return;
}
if (!globalUseTimeoutFromTimer) {
// 1. global setTimeout equals timers setTimeout
// 2. or global don't use timers setTimeout(maybe some other library patch setTimeout)
// 3. or load timers module error happens, we should patch global setTimeout
patchTimer(global, set, clear, 'Timeout');
patchTimer(global, set, clear, 'Interval');
patchTimer(global, set, clear, 'Immediate');
} else {
// global use timers setTimeout, but not equals
// this happens when use nodejs v0.10.x, global setTimeout will
// use a lazy load version of timers setTimeout
// we should not double patch timer's setTimeout
// so we only store the __symbol__ for consistency
global[Zone.__symbol__('setTimeout')] = global.setTimeout;
global[Zone.__symbol__('setInterval')] = global.setInterval;
global[Zone.__symbol__('setImmediate')] = global.setImmediate;
}
});
// patch process related methods
Zone.__load_patch('nextTick', () => {
// patch nextTick as microTask
patchMicroTask(process, 'nextTick', (self: any, args: any[]) => {
return {
name: 'process.nextTick',
args: args,
cbIdx: (args.length > 0 && typeof args[0] === 'function') ? 0 : -1,
target: process
};
});
});
Zone.__load_patch(
'handleUnhandledPromiseRejection', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
(Zone as any)[api.symbol('unhandledPromiseRejectionHandler')] =
findProcessPromiseRejectionHandler('unhandledRejection');
(Zone as any)[api.symbol('rejectionHandledHandler')] =
findProcessPromiseRejectionHandler('rejectionHandled');
// handle unhandled promise rejection
function findProcessPromiseRejectionHandler(evtName: string) {
return function(e: any) {
const eventTasks = findEventTasks(process, evtName);
eventTasks.forEach(eventTask => {
// process has added unhandledrejection event listener
// trigger the event listener
if (evtName === 'unhandledRejection') {
eventTask.invoke(e.rejection, e.promise);
} else if (evtName === 'rejectionHandled') {
eventTask.invoke(e.promise);
}
});
};
}
});
// Crypto
Zone.__load_patch('crypto', () => {
let crypto: any;
try {
crypto = require('crypto');
} catch (err) {
}
// use the generic patchMacroTask to patch crypto
if (crypto) {
const methodNames = ['randomBytes', 'pbkdf2'];
methodNames.forEach(name => {
patchMacroTask(crypto, name, (self: any, args: any[]) => {
return {
name: 'crypto.' + name,
args: args,
cbIdx: (args.length > 0 && typeof args[args.length - 1] === 'function') ?
args.length - 1 :
-1,
target: crypto
};
});
});
}
});
Zone.__load_patch('console', (global: any, Zone: ZoneType) => {
const consoleMethods =
['dir', 'log', 'info', 'error', 'warn', 'assert', 'debug', 'timeEnd', 'trace'];
consoleMethods.forEach((m: string) => {
const originalMethod = (console as any)[Zone.__symbol__(m)] = (console as any)[m];
if (originalMethod) {
(console as any)[m] = function() {
const args = ArraySlice.call(arguments);
if (Zone.current === Zone.root) {
return originalMethod.apply(this, args);
} else {
return Zone.root.run(originalMethod, this, args);
}
};
}
});
});