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

fix(node): node patched method should copy original delegate's symbol properties #1095

Merged
merged 1 commit into from
Jun 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ sudo: false
dist: trusty
cache: yarn
node_js:
- 6
- 8
env:
global:
- BROWSER_PROVIDER_READY_FILE=/tmp/sauce-connect-ready
Expand Down
33 changes: 33 additions & 0 deletions lib/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,36 @@ export function patchClass(className: string) {
}
}

export function copySymbolProperties(src: any, dest: any) {
if (typeof (Object as any).getOwnPropertySymbols !== 'function') {
return;
}
const symbols: any = (Object as any).getOwnPropertySymbols(src);
symbols.forEach((symbol: any) => {
const desc = Object.getOwnPropertyDescriptor(src, symbol);
Object.defineProperty(dest, symbol, {
get: function () {
return src[symbol];
},
set: function (value: any) {
if (desc && (!desc.writable || typeof desc.set !== 'function')) {
// if src[symbol] is not writable or not have a setter, just return
return;
}
src[symbol] = value;
},
enumerable: desc ? desc.enumerable : true,
configurable: desc ? desc.configurable : true
});
});
}

let shouldCopySymbolProperties = false;

export function setShouldCopySymbolProperties(flag: boolean) {
shouldCopySymbolProperties = flag;
}

export function patchMethod(
target: any, name: string,
patchFn: (delegate: Function, delegateName: string, name: string) => (self: any, args: any[]) =>
Expand All @@ -360,6 +390,9 @@ export function patchMethod(
return patchDelegate(this, arguments as any);
};
attachOriginToPatched(proto[name], delegate);
if (shouldCopySymbolProperties) {
copySymbolProperties(delegate, proto[name]);
}
}
}
return delegate;
Expand Down
9 changes: 2 additions & 7 deletions lib/node/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,17 @@
* 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, bindArguments, isMix, patchMacroTask, patchMethod, patchMicroTask, patchOnProperties} from '../common/utils';
import {ArraySlice, isMix, patchMacroTask, patchMicroTask} from '../common/utils';

const set = 'set';
const clear = 'clear';

Zone.__load_patch('node_util', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
api.patchOnProperties = patchOnProperties;
api.patchMethod = patchMethod;
api.bindArguments = bindArguments;
});

Zone.__load_patch('node_timers', (global: any, Zone: ZoneType) => {
// Timers
let globalUseTimeoutFromTimer = false;
Expand Down
16 changes: 16 additions & 0 deletions lib/node/node_util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* @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 {setShouldCopySymbolProperties, patchOnProperties, patchMethod, bindArguments} from '../common/utils';

Zone.__load_patch('node_util', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
api.patchOnProperties = patchOnProperties;
api.patchMethod = patchMethod;
api.bindArguments = bindArguments;
setShouldCopySymbolProperties(true);
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"dependencies": {},
"devDependencies": {
"@types/jasmine": "2.2.33",
"@types/node": "^6.0.96",
"@types/node": "^8.10.17",
"@types/systemjs": "^0.19.30",
"assert": "^1.4.1",
"bluebird": "^3.5.1",
Expand Down
59 changes: 58 additions & 1 deletion test/node/fs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/

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

describe('nodejs file system', () => {
describe('async method patch test', () => {
Expand Down Expand Up @@ -88,4 +89,60 @@ describe('nodejs file system', () => {
});
});
});
});

describe('util.promisify', () => {
it('fs.exists should work with util.promisify', (done: DoneFn) => {
const promisifyExists = util.promisify(exists);
promisifyExists(__filename).then(r => {
expect(r).toBe(true);
done();
}, err => {
fail(`should not be here with error: ${err}`);
});
});

it('fs.read should work with util.promisify', (done: DoneFn) => {
const promisifyRead = util.promisify(read);
const fd = openSync(__filename, 'r');
const stats = fstatSync(fd);
const bufferSize = stats.size;
const chunkSize = 512;
const buffer = new Buffer(bufferSize);
let bytesRead = 0;
// fd, buffer, offset, length, position, callback
promisifyRead(fd, buffer, bytesRead, chunkSize, bytesRead).then(
(value) => {
expect(value.bytesRead).toBe(chunkSize);
closeSync(fd);
done();
}, err => {
closeSync(fd);
fail(`should not be here with error: ${error}.`);
});
});

it('fs.write should work with util.promisify', (done: DoneFn) => {
const promisifyWrite = util.promisify(write);
const dest = __filename + 'write';
const fd = openSync(dest, 'a');
const stats = fstatSync(fd);
const chunkSize = 512;
const buffer = new Buffer(chunkSize);
for (let i = 0; i < chunkSize; i++) {
buffer[i] = 0;
}
// fd, buffer, offset, length, position, callback
promisifyWrite(fd, buffer, 0, chunkSize, 0).then(
(value) => {
expect(value.bytesWritten).toBe(chunkSize);
closeSync(fd);
unlinkSync(dest);
done();
}, err => {
closeSync(fd);
unlinkSync(dest);
fail(`should not be here with error: ${error}.`);
});
});
});
30 changes: 30 additions & 0 deletions test/node/timer.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* @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 { promisify } from 'util';

describe('node timer', () => {
it('util.promisify should work with setTimeout', (done: DoneFn) => {
const setTimeoutPromise = promisify(setTimeout);
setTimeoutPromise(50, 'value').then(value => {
expect(value).toEqual('value');
done();
}, error => {
fail(`should not be here with error: ${error}.`);
});
});

it('util.promisify should work with setImmediate', (done: DoneFn) => {
const setImmediatePromise = promisify(setImmediate);
setImmediatePromise('value').then(value => {
expect(value).toEqual('value');
done();
}, error => {
fail(`should not be here with error: ${error}.`);
});
});
});
1 change: 1 addition & 0 deletions test/node_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ import './node/Error.spec';
import './node/crypto.spec';
import './node/http.spec';
import './node/console.spec';
import './node/timer.spec';
6 changes: 3 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
version "2.2.33"
resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.2.33.tgz#4715cfd2ca7fbd632fc7f1784f13e637bed028c5"

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

"@types/systemjs@^0.19.30":
version "0.19.33"
Expand Down