/** * @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); } }; } }); });