| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,6 +8,7 @@ const { | |||
| 8 | 8 | FunctionPrototypeCall, | |
| 9 | 9 | NumberIsInteger, | |
| 10 | 10 | ObjectAssign, | |
| 11 | + ObjectCreate, | ||
| 11 | 12 | ObjectDefineProperties, | |
| 12 | 13 | ObjectDefineProperty, | |
| 13 | 14 | ObjectGetOwnPropertyDescriptor, | |
@@ -39,6 +40,7 @@ const { customInspectSymbol } = require('internal/util'); | |||
| 39 | 40 | const { inspect } = require('util'); | |
| 40 | 41 | ||
| 41 | 42 | const kIsEventTarget = SymbolFor('nodejs.event_target'); | |
| 43 | + const kIsNodeEventTarget = Symbol('kIsNodeEventTarget'); | ||
| 42 | 44 | ||
| 43 | 45 | const EventEmitter = require('events'); | |
| 44 | 46 | const { | |
@@ -80,6 +82,10 @@ const isTrusted = ObjectGetOwnPropertyDescriptor({ | |||
| 80 | 82 | } | |
| 81 | 83 | }, 'isTrusted').get; | |
| 82 | 84 | ||
| 85 | + function isEvent(value) { | ||
| 86 | + return typeof value?.[kType] === 'string'; | ||
| 87 | + } | ||
| 88 | + | ||
| 83 | 89 | class Event { | |
| 84 | 90 | constructor(type, options = null) { | |
| 85 | 91 | if (arguments.length === 0) | |
@@ -110,6 +116,8 @@ class Event { | |||
| 110 | 116 | } | |
| 111 | 117 | ||
| 112 | 118 | [customInspectSymbol](depth, options) { | |
| 119 | + if (!isEvent(this)) | ||
| 120 | + throw new ERR_INVALID_THIS('Event'); | ||
| 113 | 121 | const name = this.constructor.name; | |
| 114 | 122 | if (depth < 0) | |
| 115 | 123 | return name; | |
@@ -127,46 +135,111 @@ class Event { | |||
| 127 | 135 | } | |
| 128 | 136 | ||
| 129 | 137 | stopImmediatePropagation() { | |
| 138 | + if (!isEvent(this)) | ||
| 139 | + throw new ERR_INVALID_THIS('Event'); | ||
| 130 | 140 | this[kStop] = true; | |
| 131 | 141 | } | |
| 132 | 142 | ||
| 133 | 143 | preventDefault() { | |
| 144 | + if (!isEvent(this)) | ||
| 145 | + throw new ERR_INVALID_THIS('Event'); | ||
| 134 | 146 | this[kDefaultPrevented] = true; | |
| 135 | 147 | } | |
| 136 | 148 | ||
| 137 | - get target() { return this[kTarget]; } | ||
| 138 | - get currentTarget() { return this[kTarget]; } | ||
| 139 | - get srcElement() { return this[kTarget]; } | ||
| 149 | + get target() { | ||
| 150 | + if (!isEvent(this)) | ||
| 151 | + throw new ERR_INVALID_THIS('Event'); | ||
| 152 | + return this[kTarget]; | ||
| 153 | + } | ||
| 140 | 154 | ||
| 141 | - get type() { return this[kType]; } | ||
| 155 | + get currentTarget() { | ||
| 156 | + if (!isEvent(this)) | ||
| 157 | + throw new ERR_INVALID_THIS('Event'); | ||
| 158 | + return this[kTarget]; | ||
| 159 | + } | ||
| 142 | 160 | ||
| 143 | - get cancelable() { return this[kCancelable]; } | ||
| 161 | + get srcElement() { | ||
| 162 | + if (!isEvent(this)) | ||
| 163 | + throw new ERR_INVALID_THIS('Event'); | ||
| 164 | + return this[kTarget]; | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + get type() { | ||
| 168 | + if (!isEvent(this)) | ||
| 169 | + throw new ERR_INVALID_THIS('Event'); | ||
| 170 | + return this[kType]; | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + get cancelable() { | ||
| 174 | + if (!isEvent(this)) | ||
| 175 | + throw new ERR_INVALID_THIS('Event'); | ||
| 176 | + return this[kCancelable]; | ||
| 177 | + } | ||
| 144 | 178 | ||
| 145 | 179 | get defaultPrevented() { | |
| 180 | + if (!isEvent(this)) | ||
| 181 | + throw new ERR_INVALID_THIS('Event'); | ||
| 146 | 182 | return this[kCancelable] && this[kDefaultPrevented]; | |
| 147 | 183 | } | |
| 148 | 184 | ||
| 149 | - get timeStamp() { return this[kTimestamp]; } | ||
| 185 | + get timeStamp() { | ||
| 186 | + if (!isEvent(this)) | ||
| 187 | + throw new ERR_INVALID_THIS('Event'); | ||
| 188 | + return this[kTimestamp]; | ||
| 189 | + } | ||
| 150 | 190 | ||
| 151 | 191 | ||
| 152 | 192 | // The following are non-op and unused properties/methods from Web API Event. | |
| 153 | 193 | // These are not supported in Node.js and are provided purely for | |
| 154 | 194 | // API completeness. | |
| 155 | 195 | ||
| 156 | - composedPath() { return this[kIsBeingDispatched] ? [this[kTarget]] : []; } | ||
| 157 | - get returnValue() { return !this.defaultPrevented; } | ||
| 158 | - get bubbles() { return this[kBubbles]; } | ||
| 159 | - get composed() { return this[kComposed]; } | ||
| 196 | + composedPath() { | ||
| 197 | + if (!isEvent(this)) | ||
| 198 | + throw new ERR_INVALID_THIS('Event'); | ||
| 199 | + return this[kIsBeingDispatched] ? [this[kTarget]] : []; | ||
| 200 | + } | ||
| 201 | + | ||
| 202 | + get returnValue() { | ||
| 203 | + if (!isEvent(this)) | ||
| 204 | + throw new ERR_INVALID_THIS('Event'); | ||
| 205 | + return !this.defaultPrevented; | ||
| 206 | + } | ||
| 207 | + | ||
| 208 | + get bubbles() { | ||
| 209 | + if (!isEvent(this)) | ||
| 210 | + throw new ERR_INVALID_THIS('Event'); | ||
| 211 | + return this[kBubbles]; | ||
| 212 | + } | ||
| 213 | + | ||
| 214 | + get composed() { | ||
| 215 | + if (!isEvent(this)) | ||
| 216 | + throw new ERR_INVALID_THIS('Event'); | ||
| 217 | + return this[kComposed]; | ||
| 218 | + } | ||
| 219 | + | ||
| 160 | 220 | get eventPhase() { | |
| 221 | + if (!isEvent(this)) | ||
| 222 | + throw new ERR_INVALID_THIS('Event'); | ||
| 161 | 223 | return this[kIsBeingDispatched] ? Event.AT_TARGET : Event.NONE; | |
| 162 | 224 | } | |
| 163 | - get cancelBubble() { return this[kPropagationStopped]; } | ||
| 225 | + | ||
| 226 | + get cancelBubble() { | ||
| 227 | + if (!isEvent(this)) | ||
| 228 | + throw new ERR_INVALID_THIS('Event'); | ||
| 229 | + return this[kPropagationStopped]; | ||
| 230 | + } | ||
| 231 | + | ||
| 164 | 232 | set cancelBubble(value) { | |
| 233 | + if (!isEvent(this)) | ||
| 234 | + throw new ERR_INVALID_THIS('Event'); | ||
| 165 | 235 | if (value) { | |
| 166 | 236 | this.stopPropagation(); | |
| 167 | 237 | } | |
| 168 | 238 | } | |
| 239 | + | ||
| 169 | 240 | stopPropagation() { | |
| 241 | + if (!isEvent(this)) | ||
| 242 | + throw new ERR_INVALID_THIS('Event'); | ||
| 170 | 243 | this[kPropagationStopped] = true; | |
| 171 | 244 | } | |
| 172 | 245 | ||
@@ -176,12 +249,34 @@ class Event { | |||
| 176 | 249 | static BUBBLING_PHASE = 3; | |
| 177 | 250 | } | |
| 178 | 251 | ||
| 179 | - ObjectDefineProperty(Event.prototype, SymbolToStringTag, { | ||
| 180 | - writable: false, | ||
| 181 | - enumerable: false, | ||
| 182 | - configurable: true, | ||
| 183 | - value: 'Event', | ||
| 184 | - }); | ||
| 252 | + const kEnumerableProperty = ObjectCreate(null); | ||
| 253 | + kEnumerableProperty.enumerable = true; | ||
| 254 | + | ||
| 255 | + ObjectDefineProperties( | ||
| 256 | + Event.prototype, { | ||
| 257 | + [SymbolToStringTag]: { | ||
| 258 | + writable: false, | ||
| 259 | + enumerable: false, | ||
| 260 | + configurable: true, | ||
| 261 | + value: 'Event', | ||
| 262 | + }, | ||
| 263 | + stopImmediatePropagation: kEnumerableProperty, | ||
| 264 | + preventDefault: kEnumerableProperty, | ||
| 265 | + target: kEnumerableProperty, | ||
| 266 | + currentTarget: kEnumerableProperty, | ||
| 267 | + srcElement: kEnumerableProperty, | ||
| 268 | + type: kEnumerableProperty, | ||
| 269 | + cancelable: kEnumerableProperty, | ||
| 270 | + defaultPrevented: kEnumerableProperty, | ||
| 271 | + timeStamp: kEnumerableProperty, | ||
| 272 | + composedPath: kEnumerableProperty, | ||
| 273 | + returnValue: kEnumerableProperty, | ||
| 274 | + bubbles: kEnumerableProperty, | ||
| 275 | + composed: kEnumerableProperty, | ||
| 276 | + eventPhase: kEnumerableProperty, | ||
| 277 | + cancelBubble: kEnumerableProperty, | ||
| 278 | + stopPropagation: kEnumerableProperty, | ||
| 279 | + }); | ||
| 185 | 280 | ||
| 186 | 281 | class NodeCustomEvent extends Event { | |
| 187 | 282 | constructor(type, options) { | |
@@ -297,6 +392,8 @@ class EventTarget { | |||
| 297 | 392 | [kRemoveListener](size, type, listener, capture) {} | |
| 298 | 393 | ||
| 299 | 394 | addEventListener(type, listener, options = {}) { | |
| 395 | + if (!isEventTarget(this)) | ||
| 396 | + throw new ERR_INVALID_THIS('EventTarget'); | ||
| 300 | 397 | if (arguments.length < 2) | |
| 301 | 398 | throw new ERR_MISSING_ARGS('type', 'listener'); | |
| 302 | 399 | ||
@@ -368,6 +465,8 @@ class EventTarget { | |||
| 368 | 465 | } | |
| 369 | 466 | ||
| 370 | 467 | removeEventListener(type, listener, options = {}) { | |
| 468 | + if (!isEventTarget(this)) | ||
| 469 | + throw new ERR_INVALID_THIS('EventTarget'); | ||
| 371 | 470 | if (!shouldAddListener(listener)) | |
| 372 | 471 | return; | |
| 373 | 472 | ||
@@ -393,12 +492,12 @@ class EventTarget { | |||
| 393 | 492 | } | |
| 394 | 493 | ||
| 395 | 494 | dispatchEvent(event) { | |
| 396 | - if (!(event instanceof Event)) | ||
| 397 | - throw new ERR_INVALID_ARG_TYPE('event', 'Event', event); | ||
| 398 | - | ||
| 399 | 495 | if (!isEventTarget(this)) | |
| 400 | 496 | throw new ERR_INVALID_THIS('EventTarget'); | |
| 401 | 497 | ||
| 498 | + if (!(event instanceof Event)) | ||
| 499 | + throw new ERR_INVALID_ARG_TYPE('event', 'Event', event); | ||
| 500 | + | ||
| 402 | 501 | if (event[kIsBeingDispatched]) | |
| 403 | 502 | throw new ERR_EVENT_RECURSION(event.type); | |
| 404 | 503 | ||
@@ -479,6 +578,8 @@ class EventTarget { | |||
| 479 | 578 | return new NodeCustomEvent(type, { detail: nodeValue }); | |
| 480 | 579 | } | |
| 481 | 580 | [customInspectSymbol](depth, options) { | |
| 581 | + if (!isEventTarget(this)) | ||
| 582 | + throw new ERR_INVALID_THIS('EventTarget'); | ||
| 482 | 583 | const name = this.constructor.name; | |
| 483 | 584 | if (depth < 0) | |
| 484 | 585 | return name; | |
@@ -492,22 +593,23 @@ class EventTarget { | |||
| 492 | 593 | } | |
| 493 | 594 | ||
| 494 | 595 | ObjectDefineProperties(EventTarget.prototype, { | |
| 495 | - addEventListener: { enumerable: true }, | ||
| 496 | - removeEventListener: { enumerable: true }, | ||
| 497 | - dispatchEvent: { enumerable: true } | ||
| 498 | - }); | ||
| 499 | - ObjectDefineProperty(EventTarget.prototype, SymbolToStringTag, { | ||
| 500 | - writable: false, | ||
| 501 | - enumerable: false, | ||
| 502 | - configurable: true, | ||
| 503 | - value: 'EventTarget', | ||
| 596 | + addEventListener: kEnumerableProperty, | ||
| 597 | + removeEventListener: kEnumerableProperty, | ||
| 598 | + dispatchEvent: kEnumerableProperty, | ||
| 599 | + [SymbolToStringTag]: { | ||
| 600 | + writable: false, | ||
| 601 | + enumerable: false, | ||
| 602 | + configurable: true, | ||
| 603 | + value: 'EventTarget', | ||
| 604 | + } | ||
| 504 | 605 | }); | |
| 505 | 606 | ||
| 506 | 607 | function initNodeEventTarget(self) { | |
| 507 | 608 | initEventTarget(self); | |
| 508 | 609 | } | |
| 509 | 610 | ||
| 510 | 611 | class NodeEventTarget extends EventTarget { | |
| 612 | + static [kIsNodeEventTarget] = true; | ||
| 511 | 613 | static defaultMaxListeners = 10; | |
| 512 | 614 | ||
| 513 | 615 | constructor() { | |
@@ -516,55 +618,77 @@ class NodeEventTarget extends EventTarget { | |||
| 516 | 618 | } | |
| 517 | 619 | ||
| 518 | 620 | setMaxListeners(n) { | |
| 621 | + if (!isNodeEventTarget(this)) | ||
| 622 | + throw new ERR_INVALID_THIS('NodeEventTarget'); | ||
| 519 | 623 | EventEmitter.setMaxListeners(n, this); | |
| 520 | 624 | } | |
| 521 | 625 | ||
| 522 | 626 | getMaxListeners() { | |
| 627 | + if (!isNodeEventTarget(this)) | ||
| 628 | + throw new ERR_INVALID_THIS('NodeEventTarget'); | ||
| 523 | 629 | return this[kMaxEventTargetListeners]; | |
| 524 | 630 | } | |
| 525 | 631 | ||
| 526 | 632 | eventNames() { | |
| 633 | + if (!isNodeEventTarget(this)) | ||
| 634 | + throw new ERR_INVALID_THIS('NodeEventTarget'); | ||
| 527 | 635 | return ArrayFrom(this[kEvents].keys()); | |
| 528 | 636 | } | |
| 529 | 637 | ||
| 530 | 638 | listenerCount(type) { | |
| 639 | + if (!isNodeEventTarget(this)) | ||
| 640 | + throw new ERR_INVALID_THIS('NodeEventTarget'); | ||
| 531 | 641 | const root = this[kEvents].get(String(type)); | |
| 532 | 642 | return root !== undefined ? root.size : 0; | |
| 533 | 643 | } | |
| 534 | 644 | ||
| 535 | 645 | off(type, listener, options) { | |
| 646 | + if (!isNodeEventTarget(this)) | ||
| 647 | + throw new ERR_INVALID_THIS('NodeEventTarget'); | ||
| 536 | 648 | this.removeEventListener(type, listener, options); | |
| 537 | 649 | return this; | |
| 538 | 650 | } | |
| 539 | 651 | ||
| 540 | 652 | removeListener(type, listener, options) { | |
| 653 | + if (!isNodeEventTarget(this)) | ||
| 654 | + throw new ERR_INVALID_THIS('NodeEventTarget'); | ||
| 541 | 655 | this.removeEventListener(type, listener, options); | |
| 542 | 656 | return this; | |
| 543 | 657 | } | |
| 544 | 658 | ||
| 545 | 659 | on(type, listener) { | |
| 660 | + if (!isNodeEventTarget(this)) | ||
| 661 | + throw new ERR_INVALID_THIS('NodeEventTarget'); | ||
| 546 | 662 | this.addEventListener(type, listener, { [kIsNodeStyleListener]: true }); | |
| 547 | 663 | return this; | |
| 548 | 664 | } | |
| 549 | 665 | ||
| 550 | 666 | addListener(type, listener) { | |
| 667 | + if (!isNodeEventTarget(this)) | ||
| 668 | + throw new ERR_INVALID_THIS('NodeEventTarget'); | ||
| 551 | 669 | this.addEventListener(type, listener, { [kIsNodeStyleListener]: true }); | |
| 552 | 670 | return this; | |
| 553 | 671 | } | |
| 554 | 672 | emit(type, arg) { | |
| 673 | + if (!isNodeEventTarget(this)) | ||
| 674 | + throw new ERR_INVALID_THIS('NodeEventTarget'); | ||
| 555 | 675 | validateString(type, 'type'); | |
| 556 | 676 | const hadListeners = this.listenerCount(type) > 0; | |
| 557 | 677 | this[kHybridDispatch](arg, type); | |
| 558 | 678 | return hadListeners; | |
| 559 | 679 | } | |
| 560 | 680 | ||
| 561 | 681 | once(type, listener) { | |
| 682 | + if (!isNodeEventTarget(this)) | ||
| 683 | + throw new ERR_INVALID_THIS('NodeEventTarget'); | ||
| 562 | 684 | this.addEventListener(type, listener, | |
| 563 | 685 | { once: true, [kIsNodeStyleListener]: true }); | |
| 564 | 686 | return this; | |
| 565 | 687 | } | |
| 566 | 688 | ||
| 567 | 689 | removeAllListeners(type) { | |
| 690 | + if (!isNodeEventTarget(this)) | ||
| 691 | + throw new ERR_INVALID_THIS('NodeEventTarget'); | ||
| 568 | 692 | if (type !== undefined) { | |
| 569 | 693 | this[kEvents].delete(String(type)); | |
| 570 | 694 | } else { | |
@@ -576,17 +700,17 @@ class NodeEventTarget extends EventTarget { | |||
| 576 | 700 | } | |
| 577 | 701 | ||
| 578 | 702 | ObjectDefineProperties(NodeEventTarget.prototype, { | |
| 579 | - setMaxListeners: { enumerable: true }, | ||
| 580 | - getMaxListeners: { enumerable: true }, | ||
| 581 | - eventNames: { enumerable: true }, | ||
| 582 | - listenerCount: { enumerable: true }, | ||
| 583 | - off: { enumerable: true }, | ||
| 584 | - removeListener: { enumerable: true }, | ||
| 585 | - on: { enumerable: true }, | ||
| 586 | - addListener: { enumerable: true }, | ||
| 587 | - once: { enumerable: true }, | ||
| 588 | - emit: { enumerable: true }, | ||
| 589 | - removeAllListeners: { enumerable: true }, | ||
| 703 | + setMaxListeners: kEnumerableProperty, | ||
| 704 | + getMaxListeners: kEnumerableProperty, | ||
| 705 | + eventNames: kEnumerableProperty, | ||
| 706 | + listenerCount: kEnumerableProperty, | ||
| 707 | + off: kEnumerableProperty, | ||
| 708 | + removeListener: kEnumerableProperty, | ||
| 709 | + on: kEnumerableProperty, | ||
| 710 | + addListener: kEnumerableProperty, | ||
| 711 | + once: kEnumerableProperty, | ||
| 712 | + emit: kEnumerableProperty, | ||
| 713 | + removeAllListeners: kEnumerableProperty, | ||
| 590 | 714 | }); | |
| 591 | 715 | ||
| 592 | 716 | // EventTarget API | |
@@ -631,6 +755,10 @@ function isEventTarget(obj) { | |||
| 631 | 755 | return obj?.constructor?.[kIsEventTarget]; | |
| 632 | 756 | } | |
| 633 | 757 | ||
| 758 | + function isNodeEventTarget(obj) { | ||
| 759 | + return obj?.constructor?.[kIsNodeEventTarget]; | ||
| 760 | + } | ||
| 761 | + | ||
| 634 | 762 | function addCatch(promise) { | |
| 635 | 763 | const then = promise.then; | |
| 636 | 764 | if (typeof then === 'function') { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments