|
| 1 | +import '../zone'; |
| 2 | +import {patchMethod, patchPrototype, patchClass, zoneSymbol} from '../common/utils'; |
| 3 | + |
| 4 | +// TODO(juliemr): remove duplication in this file. |
| 5 | + |
| 6 | +const set = 'set'; |
| 7 | +const clear = 'clear'; |
| 8 | +const blockingMethods = ['alert', 'prompt', 'confirm']; |
| 9 | +const _global = typeof window === 'undefined' ? global : window; |
| 10 | + |
| 11 | +// Timers |
| 12 | +const timers = require('timers'); |
| 13 | +patchTimer(timers, set, clear, 'Timeout'); |
| 14 | +patchTimer(timers, set, clear, 'Interval'); |
| 15 | +patchTimer(timers, set, clear, 'Immediate'); |
| 16 | + |
| 17 | +const shouldPatchGlobalTimers = global.setTimeout !== timers.setTimeout; |
| 18 | + |
| 19 | +if (shouldPatchGlobalTimers) { |
| 20 | + patchTimer(_global, set, clear, 'Timeout'); |
| 21 | + patchTimer(_global, set, clear, 'Interval'); |
| 22 | + patchTimer(_global, set, clear, 'Immediate'); |
| 23 | +} |
| 24 | + |
| 25 | + |
| 26 | +// Crypto |
| 27 | +let crypto; |
| 28 | +try { |
| 29 | + crypto = require('crypto'); |
| 30 | +} catch (err) {} |
| 31 | + |
| 32 | +// TODO(gdi2290): implement a better way to patch these methods |
| 33 | +if (crypto) { |
| 34 | + let nativeRandomBytes = crypto.randomBytes; |
| 35 | + crypto.randomBytes = function randomBytesZone(size: number, callback?: Function) { |
| 36 | + if (!callback) { |
| 37 | + return nativeRandomBytes(size); |
| 38 | + } else { |
| 39 | + let zone = Zone.current; |
| 40 | + var source = crypto.constructor.name + '.randomBytes'; |
| 41 | + return nativeRandomBytes(size, zone.wrap(callback, source)); |
| 42 | + } |
| 43 | + }.bind(crypto); |
| 44 | + |
| 45 | + let nativePbkdf2 = crypto.pbkdf2; |
| 46 | + crypto.pbkdf2 = function pbkdf2Zone(...args) { |
| 47 | + let fn = args[args.length - 1]; |
| 48 | + if (typeof fn === 'function') { |
| 49 | + let zone = Zone.current; |
| 50 | + var source = crypto.constructor.name + '.pbkdf2'; |
| 51 | + args[args.length - 1] = zone.wrap(fn, source); |
| 52 | + return nativePbkdf2(...args); |
| 53 | + } else { |
| 54 | + return nativePbkdf2(...args); |
| 55 | + } |
| 56 | + }.bind(crypto); |
| 57 | +} |
| 58 | + |
| 59 | +interface TimerOptions extends TaskData { |
| 60 | + handleId: number; |
| 61 | + args: any[]; |
| 62 | +} |
| 63 | + |
| 64 | +function patchTimer( |
| 65 | + window: any, |
| 66 | + setName: string, |
| 67 | + cancelName: string, |
| 68 | + nameSuffix: string) { |
| 69 | + |
| 70 | + var setNative = null; |
| 71 | + var clearNative = null; |
| 72 | + setName += nameSuffix; |
| 73 | + cancelName += nameSuffix; |
| 74 | + |
| 75 | + function scheduleTask(task: Task) { |
| 76 | + const data = <TimerOptions>task.data; |
| 77 | + data.args[0] = task.invoke; |
| 78 | + data.handleId = setNative.apply(window, data.args); |
| 79 | + return task; |
| 80 | + } |
| 81 | + |
| 82 | + function clearTask(task: Task) { |
| 83 | + return clearNative((<TimerOptions>task.data).handleId); |
| 84 | + } |
| 85 | + |
| 86 | + setNative = patchMethod(window, setName, (delegate: Function) => function(self: any, args: any[]) { |
| 87 | + if (typeof args[0] === 'function') { |
| 88 | + var zone = Zone.current; |
| 89 | + var options: TimerOptions = { |
| 90 | + handleId: null, |
| 91 | + isPeriodic: nameSuffix === 'Interval', |
| 92 | + delay: (nameSuffix === 'Timeout' || nameSuffix === 'Interval') ? args[1] || 0 : null, |
| 93 | + args: args |
| 94 | + }; |
| 95 | + return zone.scheduleMacroTask(setName, args[0], options, scheduleTask, clearTask); |
| 96 | + } else { |
| 97 | + // cause an error by calling it directly. |
| 98 | + return delegate.apply(window, args); |
| 99 | + } |
| 100 | + }); |
| 101 | + |
| 102 | + clearNative = patchMethod(window, cancelName, (delegate: Function) => function(self: any, args: any[]) { |
| 103 | + var task: Task = args[0]; |
| 104 | + if (task && typeof task.type === 'string') { |
| 105 | + if (task.cancelFn && task.data.isPeriodic || task.runCount === 0) { |
| 106 | + // Do not cancel already canceled functions |
| 107 | + task.zone.cancelTask(task); |
| 108 | + } |
| 109 | + } else { |
| 110 | + // cause an error by calling it directly. |
| 111 | + delegate.apply(window, args); |
| 112 | + } |
| 113 | + }); |
| 114 | +} |
0 commit comments