From e9940decfc6933aaa5351342b275d8fc55380342 Mon Sep 17 00:00:00 2001 From: "JiaLi.Passion" Date: Tue, 17 Jul 2018 15:56:26 +0900 Subject: [PATCH] fix(event): fix #1110, nodejs EventEmitter should support Symbol eventName --- file-size-limit.json | 2 +- lib/common/events.ts | 16 ++++++++++++---- lib/node/events.ts | 13 ++++++++++++- test/node/events.spec.ts | 12 ++++++++++++ tsconfig-esm-node.json | 3 ++- tsconfig-esm.json | 9 ++++++++- tsconfig-node.json | 3 ++- tsconfig.json | 9 ++++++++- 8 files changed, 57 insertions(+), 10 deletions(-) diff --git a/file-size-limit.json b/file-size-limit.json index e0fd98bf9..bd147342a 100644 --- a/file-size-limit.json +++ b/file-size-limit.json @@ -3,7 +3,7 @@ { "path": "dist/zone.min.js", "checkTarget": true, - "limit": 42500 + "limit": 43000 } ] } diff --git a/lib/common/events.ts b/lib/common/events.ts index b2a02f69c..ff2442dfe 100644 --- a/lib/common/events.ts +++ b/lib/common/events.ts @@ -69,6 +69,8 @@ export interface PatchEventTargetOptions { diff?: (task: any, delegate: any) => boolean; // support passive or not supportPassive?: boolean; + // get string from eventName (in nodejs, eventName maybe Symbol) + eventNameToString?: (eventName: any) => string; } export function patchEventTarget( @@ -212,6 +214,8 @@ export function patchEventTarget( return false; } + const eventNameToString = patchOptions && patchOptions.eventNameToString; + // a shared global taskData to pass data for scheduleEventTask // so we do not need to create a new object just for pass some data const taskData: any = {}; @@ -384,8 +388,10 @@ export function patchEventTarget( let symbolEventName; if (!symbolEventNames) { // the code is duplicate, but I just want to get some better performance - const falseEventName = eventName + FALSE_STR; - const trueEventName = eventName + TRUE_STR; + const falseEventName = + (eventNameToString ? eventNameToString(eventName) : eventName) + FALSE_STR; + const trueEventName = + (eventNameToString ? eventNameToString(eventName) : eventName) + TRUE_STR; const symbol = ZONE_SYMBOL_PREFIX + falseEventName; const symbolCapture = ZONE_SYMBOL_PREFIX + trueEventName; zoneSymbolEventNames[eventName] = {}; @@ -418,7 +424,8 @@ export function patchEventTarget( source = targetSource[eventName]; } if (!source) { - source = constructorName + addSource + eventName; + source = constructorName + addSource + + (eventNameToString ? eventNameToString(eventName) : eventName); } // do not create a new object as task.data to pass those things // just use the global shared one @@ -556,7 +563,8 @@ export function patchEventTarget( const eventName = arguments[0]; const listeners: any[] = []; - const tasks = findEventTasks(target, eventName); + const tasks = + findEventTasks(target, eventNameToString ? eventNameToString(eventName) : eventName); for (let i = 0; i < tasks.length; i++) { const task: any = tasks[i]; diff --git a/lib/node/events.ts b/lib/node/events.ts index d7eda2596..09ab0c856 100644 --- a/lib/node/events.ts +++ b/lib/node/events.ts @@ -22,6 +22,16 @@ Zone.__load_patch('EventEmitter', (global: any) => { return task.callback === delegate || task.callback.listener === delegate; }; + const eventNameToString = function(eventName: string|Symbol) { + if (typeof eventName === 'string') { + return eventName as string; + } + if (!eventName) { + return ''; + } + return eventName.toString().replace('(', '_').replace(')', '_'); + }; + function patchEventEmitterMethods(obj: any) { const result = patchEventTarget(global, [obj], { useG: false, @@ -32,7 +42,8 @@ Zone.__load_patch('EventEmitter', (global: any) => { listeners: EE_LISTENERS, chkDup: false, rt: true, - diff: compareTaskCallbackVsDelegate + diff: compareTaskCallbackVsDelegate, + eventNameToString: eventNameToString }); if (result && result[0]) { obj[EE_ON] = obj[EE_ADD_LISTENER]; diff --git a/test/node/events.spec.ts b/test/node/events.spec.ts index 8b13c8012..09757e2aa 100644 --- a/test/node/events.spec.ts +++ b/test/node/events.spec.ts @@ -189,4 +189,16 @@ describe('nodejs EventEmitter', () => { process.on('uncaughtException', function() {}); }); }); + it('should be able to addEventListener with symbol eventName', () => { + zoneA.run(() => { + const testSymbol = Symbol('test'); + const test1Symbol = Symbol('test1'); + emitter.on(testSymbol, expectZoneA); + emitter.on(test1Symbol, shouldNotRun); + emitter.removeListener(test1Symbol, shouldNotRun); + expect(emitter.listeners(testSymbol).length).toBe(1); + expect(emitter.listeners(test1Symbol).length).toBe(0); + emitter.emit(testSymbol, 'test value'); + }); + }); }); diff --git a/tsconfig-esm-node.json b/tsconfig-esm-node.json index 8a79dc143..7bc17d63b 100644 --- a/tsconfig-esm-node.json +++ b/tsconfig-esm-node.json @@ -18,7 +18,8 @@ "lib": [ "es5", "dom", - "es2015.promise" + "es2015.promise", + "es2015.symbol" ] }, "exclude": [ diff --git a/tsconfig-esm.json b/tsconfig-esm.json index ab2416b2d..6fd80e075 100644 --- a/tsconfig-esm.json +++ b/tsconfig-esm.json @@ -26,6 +26,13 @@ "build", "build-esm", "dist", - "lib/closure" + "lib/closure", + "lib/node/**", + "lib/mix/**", + "test/node/**", + "test/node_bluebird_entry_point.ts", + "test/node_entry_point.ts", + "test/node_error_entry_point.ts", + "test/node_tests.ts" ] } \ No newline at end of file diff --git a/tsconfig-node.json b/tsconfig-node.json index eca611773..f33fd87af 100644 --- a/tsconfig-node.json +++ b/tsconfig-node.json @@ -16,7 +16,8 @@ "lib": [ "es5", "dom", - "es2015.promise" + "es2015.promise", + "es2015.symbol" ] }, "exclude": [ diff --git a/tsconfig.json b/tsconfig.json index ec1d893a9..90ba090fc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,6 +23,13 @@ "build", "build-esm", "dist", - "lib/closure" + "lib/closure", + "lib/node/**", + "lib/mix/**", + "test/node/**", + "test/node_bluebird_entry_point.ts", + "test/node_entry_point.ts", + "test/node_error_entry_point.ts", + "test/node_tests.ts" ] } \ No newline at end of file