Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit 29fc5d2

Browse files
PatrickJSjuliemr
authored andcommitted
feat: node/node
Add a starting point for Zones-for-Node.js.
1 parent 6945852 commit 29fc5d2

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

Diff for: gulpfile.js

+2
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,12 @@ gulp.task('build/zone.js.d.ts', ['compile'], function() {
6161
return gulp.src('./build/lib/zone.d.ts').pipe(rename('zone.js.d.ts')).pipe(gulp.dest('./dist'));
6262
});
6363

64+
// Zone for Node.js environment.
6465
gulp.task('build/zone-node.js', function(cb) {
6566
return generateBrowserScript('./lib/node/node.ts', 'zone-node.js', false, cb);
6667
});
6768

69+
// Zone for the browser.
6870
gulp.task('build/zone.js', function(cb) {
6971
return generateBrowserScript('./lib/browser/browser.ts', 'zone.js', false, cb);
7072
});

Diff for: lib/node/node.ts

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
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

Comments
 (0)