| 
									
										
										
										
											2019-06-01 00:56:07 +09:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							| 
									
										
										
										
											2020-05-19 12:08:49 -07:00
										 |  |  |  * Copyright Google LLC All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2019-06-01 00:56:07 +09:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); |