diff --git a/lib/events.js b/lib/events.js index b47fadd64752e3..f1dcdf86f794dd 100644 --- a/lib/events.js +++ b/lib/events.js @@ -87,34 +87,21 @@ EventEmitter.init = function() { const proxyEventsHandler = { deleteProperty({ emitter }, prop) { const events = emitter[kEvents]; - if (events === undefined) - return false; - if (!events.has(prop) && - typeof prop !== 'string' && - typeof prop !== 'symbol') - prop = String(prop); - return events.delete(prop); + if (events !== undefined) + events.delete(prop); + return true; }, get({ emitter }, prop) { const events = emitter[kEvents]; if (events === undefined) return; - let value = events.get(prop); - if (value === undefined && - typeof prop !== 'string' && - typeof prop !== 'symbol') - value = events.get(String(prop)); - return value; + return events.get(prop); }, getOwnPropertyDescriptor({ emitter }, prop) { const events = emitter[kEvents]; if (events === undefined) return undefined; - let value = events.get(prop); - if (value === undefined && - typeof prop !== 'string' && - typeof prop !== 'symbol') - value = events.get(String(prop)); + const value = events.get(prop); if (value === undefined) return undefined; return { @@ -131,22 +118,13 @@ const proxyEventsHandler = { const events = emitter[kEvents]; if (events === undefined) return false; - let has = events.has(prop); - if (!has && typeof prop !== 'string' && typeof prop !== 'symbol') - has = events.has(String(prop)); - return has; + return events.has(prop); }, ownKeys({ emitter }) { const events = emitter[kEvents]; - if (events === undefined) + if (events === undefined || events.size === 0) return []; - const keys = new Array(events.size); - var i = 0; - for (var [key] of events) { - keys[i++] = typeof key !== 'string' && typeof key !== 'symbol' ? - String(key) : key; - } - return keys; + return [...events.keys()]; }, set({ emitter }, prop, value) { let events = emitter[kEvents]; @@ -164,7 +142,8 @@ Object.defineProperty(EventEmitter.prototype, '_events', { const proxy = this[kEventsProxy]; // The proxy target has to be an empty object with a single configurable // key, because of rules around Proxy handler.ownKeys behaviour - if (proxy === undefined) + if (proxy === undefined || + this[kEventsProxy] === Object.getPrototypeOf(this)[kEventsProxy]) return this[kEventsProxy] = new Proxy({ emitter: this }, proxyEventsHandler); return proxy; diff --git a/test/parallel/test-event-emitter-proxy.js b/test/parallel/test-event-emitter-proxy.js new file mode 100644 index 00000000000000..cee376d0306f8f --- /dev/null +++ b/test/parallel/test-event-emitter-proxy.js @@ -0,0 +1,43 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const EventEmitter = require('events'); + +const _events = EventEmitter.prototype._events; + +const ee = new EventEmitter(); +const noop = () => {}; + +assert.notStrictEqual(_events, ee._events); + +assert(!(ee._events instanceof Object)); +assert.notStrictEqual(ee._events, undefined); +assert.deepStrictEqual(Object.keys(ee._events), []); +assert.strictEqual(ee._events.foo, undefined); +assert.doesNotThrow(() => delete ee._events.foo); +assert.strictEqual('foo' in ee._events, false); +assert.strictEqual(Object.getOwnPropertyDescriptor(ee._events, 'foo'), + undefined); + +assert.doesNotThrow(() => ee._events.foo = noop); + +assert.strictEqual(ee._events.foo, noop); +assert.deepStrictEqual(Object.keys(ee._events), ['foo']); +assert.deepStrictEqual(ee.listeners('foo'), [noop]); +assert.strictEqual('foo' in ee._events, true); +assert.deepStrictEqual(Object.getOwnPropertyDescriptor(ee._events, 'foo'), + { + value: noop, + writable: true, + configurable: true, + enumerable: true + }); + +assert.doesNotThrow(() => delete ee._events.foo); +assert.strictEqual(ee._events.foo, undefined); +assert.deepStrictEqual(Object.keys(ee._events), []); +assert.strictEqual('foo' in ee._events, false); +assert.strictEqual(ee.listenerCount('foo'), 0); +assert.strictEqual(Object.getOwnPropertyDescriptor(ee._events, 'foo'), + undefined);