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

Commit 0a2f6ff

Browse files
JiaLiPassionmhevery
authored andcommittedJun 18, 2018
fix(node): node patched method should copy original delegate's symbol properties (#1095)
1 parent d7e0a31 commit 0a2f6ff

File tree

9 files changed

+145
-13
lines changed

9 files changed

+145
-13
lines changed
 

‎.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ sudo: false
33
dist: trusty
44
cache: yarn
55
node_js:
6-
- 6
6+
- 8
77
env:
88
global:
99
- BROWSER_PROVIDER_READY_FILE=/tmp/sauce-connect-ready

‎lib/common/utils.ts

+33
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,36 @@ export function patchClass(className: string) {
334334
}
335335
}
336336

337+
export function copySymbolProperties(src: any, dest: any) {
338+
if (typeof (Object as any).getOwnPropertySymbols !== 'function') {
339+
return;
340+
}
341+
const symbols: any = (Object as any).getOwnPropertySymbols(src);
342+
symbols.forEach((symbol: any) => {
343+
const desc = Object.getOwnPropertyDescriptor(src, symbol);
344+
Object.defineProperty(dest, symbol, {
345+
get: function () {
346+
return src[symbol];
347+
},
348+
set: function (value: any) {
349+
if (desc && (!desc.writable || typeof desc.set !== 'function')) {
350+
// if src[symbol] is not writable or not have a setter, just return
351+
return;
352+
}
353+
src[symbol] = value;
354+
},
355+
enumerable: desc ? desc.enumerable : true,
356+
configurable: desc ? desc.configurable : true
357+
});
358+
});
359+
}
360+
361+
let shouldCopySymbolProperties = false;
362+
363+
export function setShouldCopySymbolProperties(flag: boolean) {
364+
shouldCopySymbolProperties = flag;
365+
}
366+
337367
export function patchMethod(
338368
target: any, name: string,
339369
patchFn: (delegate: Function, delegateName: string, name: string) => (self: any, args: any[]) =>
@@ -360,6 +390,9 @@ export function patchMethod(
360390
return patchDelegate(this, arguments as any);
361391
};
362392
attachOriginToPatched(proto[name], delegate);
393+
if (shouldCopySymbolProperties) {
394+
copySymbolProperties(delegate, proto[name]);
395+
}
363396
}
364397
}
365398
return delegate;

‎lib/node/node.ts

+2-7
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,17 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9+
import './node_util';
910
import './events';
1011
import './fs';
1112

1213
import {findEventTasks} from '../common/events';
1314
import {patchTimer} from '../common/timers';
14-
import {ArraySlice, bindArguments, isMix, patchMacroTask, patchMethod, patchMicroTask, patchOnProperties} from '../common/utils';
15+
import {ArraySlice, isMix, patchMacroTask, patchMicroTask} from '../common/utils';
1516

1617
const set = 'set';
1718
const clear = 'clear';
1819

19-
Zone.__load_patch('node_util', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
20-
api.patchOnProperties = patchOnProperties;
21-
api.patchMethod = patchMethod;
22-
api.bindArguments = bindArguments;
23-
});
24-
2520
Zone.__load_patch('node_timers', (global: any, Zone: ZoneType) => {
2621
// Timers
2722
let globalUseTimeoutFromTimer = false;

‎lib/node/node_util.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {setShouldCopySymbolProperties, patchOnProperties, patchMethod, bindArguments} from '../common/utils';
10+
11+
Zone.__load_patch('node_util', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
12+
api.patchOnProperties = patchOnProperties;
13+
api.patchMethod = patchMethod;
14+
api.bindArguments = bindArguments;
15+
setShouldCopySymbolProperties(true);
16+
});

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
"dependencies": {},
6060
"devDependencies": {
6161
"@types/jasmine": "2.2.33",
62-
"@types/node": "^6.0.96",
62+
"@types/node": "^8.10.17",
6363
"@types/systemjs": "^0.19.30",
6464
"assert": "^1.4.1",
6565
"bluebird": "^3.5.1",

‎test/node/fs.spec.ts

+58-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {exists, unlink, unwatchFile, watch, watchFile, writeFile} from 'fs';
9+
import {exists, read, unlink, unwatchFile, watch, write, watchFile, writeFile, openSync, fstatSync, closeSync, unlinkSync} from 'fs';
10+
import * as util from 'util';
1011

1112
describe('nodejs file system', () => {
1213
describe('async method patch test', () => {
@@ -88,4 +89,60 @@ describe('nodejs file system', () => {
8889
});
8990
});
9091
});
92+
});
93+
94+
describe('util.promisify', () => {
95+
it('fs.exists should work with util.promisify', (done: DoneFn) => {
96+
const promisifyExists = util.promisify(exists);
97+
promisifyExists(__filename).then(r => {
98+
expect(r).toBe(true);
99+
done();
100+
}, err => {
101+
fail(`should not be here with error: ${err}`);
102+
});
103+
});
104+
105+
it('fs.read should work with util.promisify', (done: DoneFn) => {
106+
const promisifyRead = util.promisify(read);
107+
const fd = openSync(__filename, 'r');
108+
const stats = fstatSync(fd);
109+
const bufferSize = stats.size;
110+
const chunkSize = 512;
111+
const buffer = new Buffer(bufferSize);
112+
let bytesRead = 0;
113+
// fd, buffer, offset, length, position, callback
114+
promisifyRead(fd, buffer, bytesRead, chunkSize, bytesRead).then(
115+
(value) => {
116+
expect(value.bytesRead).toBe(chunkSize);
117+
closeSync(fd);
118+
done();
119+
}, err => {
120+
closeSync(fd);
121+
fail(`should not be here with error: ${error}.`);
122+
});
123+
});
124+
125+
it('fs.write should work with util.promisify', (done: DoneFn) => {
126+
const promisifyWrite = util.promisify(write);
127+
const dest = __filename + 'write';
128+
const fd = openSync(dest, 'a');
129+
const stats = fstatSync(fd);
130+
const chunkSize = 512;
131+
const buffer = new Buffer(chunkSize);
132+
for (let i = 0; i < chunkSize; i++) {
133+
buffer[i] = 0;
134+
}
135+
// fd, buffer, offset, length, position, callback
136+
promisifyWrite(fd, buffer, 0, chunkSize, 0).then(
137+
(value) => {
138+
expect(value.bytesWritten).toBe(chunkSize);
139+
closeSync(fd);
140+
unlinkSync(dest);
141+
done();
142+
}, err => {
143+
closeSync(fd);
144+
unlinkSync(dest);
145+
fail(`should not be here with error: ${error}.`);
146+
});
147+
});
91148
});

‎test/node/timer.spec.ts

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
import { promisify } from 'util';
9+
10+
describe('node timer', () => {
11+
it('util.promisify should work with setTimeout', (done: DoneFn) => {
12+
const setTimeoutPromise = promisify(setTimeout);
13+
setTimeoutPromise(50, 'value').then(value => {
14+
expect(value).toEqual('value');
15+
done();
16+
}, error => {
17+
fail(`should not be here with error: ${error}.`);
18+
});
19+
});
20+
21+
it('util.promisify should work with setImmediate', (done: DoneFn) => {
22+
const setImmediatePromise = promisify(setImmediate);
23+
setImmediatePromise('value').then(value => {
24+
expect(value).toEqual('value');
25+
done();
26+
}, error => {
27+
fail(`should not be here with error: ${error}.`);
28+
});
29+
});
30+
});

‎test/node_tests.ts

+1
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ import './node/Error.spec';
1313
import './node/crypto.spec';
1414
import './node/http.spec';
1515
import './node/console.spec';
16+
import './node/timer.spec';

‎yarn.lock

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
version "2.2.33"
77
resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.2.33.tgz#4715cfd2ca7fbd632fc7f1784f13e637bed028c5"
88

9-
"@types/node@^6.0.96":
10-
version "6.0.101"
11-
resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.101.tgz#0c5911cfb434af4a51c0a499931fe6423207d921"
9+
"@types/node@^8.10.17":
10+
version "8.10.17"
11+
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.17.tgz#d48cf10f0dc6dcf59f827f5a3fc7a4a6004318d3"
1212

1313
"@types/systemjs@^0.19.30":
1414
version "0.19.33"

0 commit comments

Comments
 (0)
This repository has been archived.