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

fix(patch): fix #744, add namespace to load patch name #774

Merged
merged 3 commits into from
May 19, 2017
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 gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ gulp.task('build/zone.js.d.ts', ['compile-esm'], function() {

// Zone for Node.js environment.
gulp.task('build/zone-node.js', ['compile-esm'], function(cb) {
return generateScript('./lib/node/node.ts', 'zone-node.js', false, cb);
return generateScript('./lib/node/rollup-main.ts', 'zone-node.js', false, cb);
});

// Zone for the browser.
Expand Down
2 changes: 0 additions & 2 deletions lib/browser/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/

import '../common/to-string';

import {patchTimer} from '../common/timers';
import {findEventTask, patchClass, patchEventTargetMethods, patchMethod, patchPrototype, zoneSymbol} from '../common/utils';

Expand Down
2 changes: 1 addition & 1 deletion lib/browser/rollup-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/


import '../zone';
import '../common/promise';
import '../common/to-string';
import './browser';
3 changes: 2 additions & 1 deletion lib/mix/rollup-mix.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 '../zone';
import '../common/promise';
import '../common/to-string';
import '../browser/browser';
import '../node/node';
86 changes: 44 additions & 42 deletions lib/node/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,52 +8,54 @@

import {makeZoneAwareAddListener, makeZoneAwareListeners, makeZoneAwareRemoveAllListeners, makeZoneAwareRemoveListener, patchMethod} from '../common/utils';

const callAndReturnFirstParam = (fn: (self: any, args: any[]) => any) => {
return (self: any, args: any[]) => {
fn(self, args);
return self;
Zone.__load_patch('EventEmitter', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
const callAndReturnFirstParam = (fn: (self: any, args: any[]) => any) => {
return (self: any, args: any[]) => {
fn(self, args);
return self;
};
};
};

// For EventEmitter
const EE_ADD_LISTENER = 'addListener';
const EE_PREPEND_LISTENER = 'prependListener';
const EE_REMOVE_LISTENER = 'removeListener';
const EE_REMOVE_ALL_LISTENER = 'removeAllListeners';
const EE_LISTENERS = 'listeners';
const EE_ON = 'on';
// For EventEmitter
const EE_ADD_LISTENER = 'addListener';
const EE_PREPEND_LISTENER = 'prependListener';
const EE_REMOVE_LISTENER = 'removeListener';
const EE_REMOVE_ALL_LISTENER = 'removeAllListeners';
const EE_LISTENERS = 'listeners';
const EE_ON = 'on';

const zoneAwareAddListener = callAndReturnFirstParam(
makeZoneAwareAddListener(EE_ADD_LISTENER, EE_REMOVE_LISTENER, false, true, false));
const zoneAwarePrependListener = callAndReturnFirstParam(
makeZoneAwareAddListener(EE_PREPEND_LISTENER, EE_REMOVE_LISTENER, false, true, true));
const zoneAwareRemoveListener =
callAndReturnFirstParam(makeZoneAwareRemoveListener(EE_REMOVE_LISTENER, false));
const zoneAwareRemoveAllListeners =
callAndReturnFirstParam(makeZoneAwareRemoveAllListeners(EE_REMOVE_ALL_LISTENER));
const zoneAwareListeners = makeZoneAwareListeners(EE_LISTENERS);
const zoneAwareAddListener = callAndReturnFirstParam(
makeZoneAwareAddListener(EE_ADD_LISTENER, EE_REMOVE_LISTENER, false, true, false));
const zoneAwarePrependListener = callAndReturnFirstParam(
makeZoneAwareAddListener(EE_PREPEND_LISTENER, EE_REMOVE_LISTENER, false, true, true));
const zoneAwareRemoveListener =
callAndReturnFirstParam(makeZoneAwareRemoveListener(EE_REMOVE_LISTENER, false));
const zoneAwareRemoveAllListeners =
callAndReturnFirstParam(makeZoneAwareRemoveAllListeners(EE_REMOVE_ALL_LISTENER));
const zoneAwareListeners = makeZoneAwareListeners(EE_LISTENERS);

export function patchEventEmitterMethods(obj: any): boolean {
if (obj && obj.addListener) {
patchMethod(obj, EE_ADD_LISTENER, () => zoneAwareAddListener);
patchMethod(obj, EE_PREPEND_LISTENER, () => zoneAwarePrependListener);
patchMethod(obj, EE_REMOVE_LISTENER, () => zoneAwareRemoveListener);
patchMethod(obj, EE_REMOVE_ALL_LISTENER, () => zoneAwareRemoveAllListeners);
patchMethod(obj, EE_LISTENERS, () => zoneAwareListeners);
obj[EE_ON] = obj[EE_ADD_LISTENER];
return true;
} else {
return false;
function patchEventEmitterMethods(obj: any): boolean {
if (obj && obj.addListener) {
patchMethod(obj, EE_ADD_LISTENER, () => zoneAwareAddListener);
patchMethod(obj, EE_PREPEND_LISTENER, () => zoneAwarePrependListener);
patchMethod(obj, EE_REMOVE_LISTENER, () => zoneAwareRemoveListener);
patchMethod(obj, EE_REMOVE_ALL_LISTENER, () => zoneAwareRemoveAllListeners);
patchMethod(obj, EE_LISTENERS, () => zoneAwareListeners);
obj[EE_ON] = obj[EE_ADD_LISTENER];
return true;
} else {
return false;
}
}
}

// EventEmitter
let events;
try {
events = require('events');
} catch (err) {
}
// EventEmitter
let events;
try {
events = require('events');
} catch (err) {
}

if (events && events.EventEmitter) {
patchEventEmitterMethods(events.EventEmitter.prototype);
}
if (events && events.EventEmitter) {
patchEventEmitterMethods(events.EventEmitter.prototype);
}
});
54 changes: 28 additions & 26 deletions lib/node/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,34 @@

import {patchMacroTask} from '../common/utils';

let fs: any;
try {
fs = require('fs');
} catch (err) {
}
Zone.__load_patch('fs', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
let fs: any;
try {
fs = require('fs');
} catch (err) {
}

// watch, watchFile, unwatchFile has been patched
// because EventEmitter has been patched
const TO_PATCH_MACROTASK_METHODS = [
'access', 'appendFile', 'chmod', 'chown', 'close', 'exists', 'fchmod',
'fchown', 'fdatasync', 'fstat', 'fsync', 'ftruncate', 'futimes', 'lchmod',
'lchown', 'link', 'lstat', 'mkdir', 'mkdtemp', 'open', 'read',
'readdir', 'readFile', 'readlink', 'realpath', 'rename', 'rmdir', 'stat',
'symlink', 'truncate', 'unlink', 'utimes', 'write', 'writeFile',
];
// watch, watchFile, unwatchFile has been patched
// because EventEmitter has been patched
const TO_PATCH_MACROTASK_METHODS = [
'access', 'appendFile', 'chmod', 'chown', 'close', 'exists', 'fchmod',
'fchown', 'fdatasync', 'fstat', 'fsync', 'ftruncate', 'futimes', 'lchmod',
'lchown', 'link', 'lstat', 'mkdir', 'mkdtemp', 'open', 'read',
'readdir', 'readFile', 'readlink', 'realpath', 'rename', 'rmdir', 'stat',
'symlink', 'truncate', 'unlink', 'utimes', 'write', 'writeFile',
];

if (fs) {
TO_PATCH_MACROTASK_METHODS.filter(name => !!fs[name] && typeof fs[name] === 'function')
.forEach(name => {
patchMacroTask(fs, name, (self: any, args: any[]) => {
return {
name: 'fs.' + name,
args: args,
callbackIndex: args.length > 0 ? args.length - 1 : -1,
target: self
};
if (fs) {
TO_PATCH_MACROTASK_METHODS.filter(name => !!fs[name] && typeof fs[name] === 'function')
.forEach(name => {
patchMacroTask(fs, name, (self: any, args: any[]) => {
return {
name: 'fs.' + name,
args: args,
callbackIndex: args.length > 0 ? args.length - 1 : -1,
target: self
};
});
});
});
}
}
});
20 changes: 13 additions & 7 deletions lib/node/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,26 @@
* found in the LICENSE file at https://angular.io/license
*/

import '../zone';
import '../common/promise';
import '../common/to-string';
import './events';
import './fs';

import {patchTimer} from '../common/timers';
import {findEventTask, patchMacroTask, patchMicroTask} from '../common/utils';
import {findEventTask, isMix, patchMacroTask, patchMicroTask} from '../common/utils';

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

Zone.__load_patch('timers', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
Zone.__load_patch('node_timers', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
// Timers
let globalUseTimeoutFromTimer = false;
try {
const timers = require('timers');
let globalEqualTimersTimeout = global.setTimeout === timers.setTimeout;
if (!globalEqualTimersTimeout) {
// if global.setTimeout not equal timers.setTimeout, check
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() {
Expand All @@ -43,6 +43,12 @@ Zone.__load_patch('timers', (global: any, Zone: ZoneType, api: _ZonePrivate) =>
// 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;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JiaLiPassion can you explain how global.setTimeout is patched already? I'm using Zone in mixed environment (Jest with jsdom), and I apparently need global.setTimeout to be patched, so fakeAsync from Angular test utils can work properly. But because it exits early, this line is not reached.

This very line essentially breaks Angular testing with fakeAsync in Jest. We're tracking this under thymikee/jest-preset-angular#65.

Any help appreciated.

}
if (!globalUseTimeoutFromTimer) {
// 1. global setTimeout equals timers setTimeout
// 2. or global don't use timers setTimeout(maybe some other library patch setTimeout)
Expand Down
12 changes: 12 additions & 0 deletions lib/node/rollup-main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* @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 '../zone';
import '../common/promise';
import '../common/to-string';
import './node';
1 change: 1 addition & 0 deletions test/browser-zone-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import '../lib/common/to-string';
import '../lib/browser/browser';
import '../lib/zone-spec/async-test';
import '../lib/zone-spec/fake-async-test';
Expand Down
2 changes: 2 additions & 0 deletions test/node_entry_point.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import './custom_error';

// Setup tests for Zone without microtask support
import '../lib/zone';
import '../lib/common/promise';
import '../lib/common/to-string';
import '../lib/node/node';
import '../lib/zone-spec/async-test';
import '../lib/zone-spec/fake-async-test';
Expand Down