|
9 | 9 | ObjectDefineProperties, |
10 | 10 | ObjectDefineProperty, |
11 | 11 | ObjectGetOwnPropertyDescriptor, |
| 12 | + ReflectApply, |
12 | 13 | SafeMap, |
13 | 14 | String, |
14 | 15 | Symbol, |
@@ -578,24 +579,47 @@ function emitUnhandledRejectionOrErr(that, err, event) { |
578 | 579 | process.emit('error', err, event); |
579 | 580 | } |
580 | 581 |
|
| 582 | +function makeEventHandler(handler) { |
| 583 | + // Event handlers are dispatched in the order they were first set |
| 584 | + // See https://github.com/nodejs/node/pull/35949#issuecomment-722496598 |
| 585 | + function eventHandler(...args) { |
| 586 | + if (typeof eventHandler.handler !== 'function') { |
| 587 | + return; |
| 588 | + } |
| 589 | + return ReflectApply(eventHandler.handler, this, args); |
| 590 | + } |
| 591 | + eventHandler.handler = handler; |
| 592 | + return eventHandler; |
| 593 | +} |
| 594 | + |
581 | 595 | function defineEventHandler(emitter, name) { |
582 | 596 | // 8.1.5.1 Event handlers - basically `on[eventName]` attributes |
583 | 597 | ObjectDefineProperty(emitter, `on${name}`, { |
584 | 598 | get() { |
585 | | - return this[kHandlers]?.get(name); |
| 599 | + return this[kHandlers]?.get(name)?.handler; |
586 | 600 | }, |
587 | 601 | set(value) { |
588 | | - const oldValue = this[kHandlers]?.get(name); |
589 | | - if (oldValue) { |
590 | | - this.removeEventListener(name, oldValue); |
591 | | - } |
592 | | - if (typeof value === 'function') { |
593 | | - this.addEventListener(name, value); |
594 | | - } |
595 | 602 | if (!this[kHandlers]) { |
596 | 603 | this[kHandlers] = new SafeMap(); |
597 | 604 | } |
598 | | - this[kHandlers].set(name, value); |
| 605 | + let wrappedHandler = this[kHandlers]?.get(name); |
| 606 | + if (wrappedHandler) { |
| 607 | + if (typeof wrappedHandler.handler === 'function') { |
| 608 | + this[kEvents].get(name).size--; |
| 609 | + const size = this[kEvents].get(name).size; |
| 610 | + this[kRemoveListener](size, name, wrappedHandler.handler, false); |
| 611 | + } |
| 612 | + wrappedHandler.handler = value; |
| 613 | + if (typeof wrappedHandler.handler === 'function') { |
| 614 | + this[kEvents].get(name).size++; |
| 615 | + const size = this[kEvents].get(name).size; |
| 616 | + this[kNewListener](size, name, value, false, false, false); |
| 617 | + } |
| 618 | + } else { |
| 619 | + wrappedHandler = makeEventHandler(value); |
| 620 | + this.addEventListener(name, wrappedHandler); |
| 621 | + } |
| 622 | + this[kHandlers].set(name, wrappedHandler); |
599 | 623 | }, |
600 | 624 | configurable: true, |
601 | 625 | enumerable: true |
|
0 commit comments