diff --git a/lib/.eslintrc.yaml b/lib/.eslintrc.yaml index c2175e97b3ed59..9bd1b44de87c34 100644 --- a/lib/.eslintrc.yaml +++ b/lib/.eslintrc.yaml @@ -67,7 +67,7 @@ rules: - name: MessageChannel message: Use `const { MessageChannel } = require('internal/worker/io');` instead of the global. - name: MessageEvent - message: Use `const { MessageEvent } = require('internal/worker/io');` instead of the global. + message: Use `const { MessageEvent } = require('internal/deps/undici/undici');` instead of the global. - name: MessagePort message: Use `const { MessagePort } = require('internal/worker/io');` instead of the global. - name: Navigator diff --git a/lib/internal/bootstrap/web/exposed-window-or-worker.js b/lib/internal/bootstrap/web/exposed-window-or-worker.js index c19c33eac260f3..efa931f6a6e3b4 100644 --- a/lib/internal/bootstrap/web/exposed-window-or-worker.js +++ b/lib/internal/bootstrap/web/exposed-window-or-worker.js @@ -39,7 +39,7 @@ defineLazyProperties(globalThis, 'buffer', ['atob', 'btoa']); // https://html.spec.whatwg.org/multipage/web-messaging.html#broadcasting-to-other-browsing-contexts exposeLazyInterfaces(globalThis, 'internal/worker/io', ['BroadcastChannel']); exposeLazyInterfaces(globalThis, 'internal/worker/io', [ - 'MessageChannel', 'MessagePort', 'MessageEvent', + 'MessageChannel', 'MessagePort', ]); // https://www.w3.org/TR/FileAPI/#dfn-Blob exposeLazyInterfaces(globalThis, 'internal/blob', ['Blob']); @@ -78,7 +78,7 @@ ObjectDefineProperty(globalThis, 'fetch', { // https://fetch.spec.whatwg.org/#request-class // https://fetch.spec.whatwg.org/#response-class exposeLazyInterfaces(globalThis, 'internal/deps/undici/undici', [ - 'FormData', 'Headers', 'Request', 'Response', + 'FormData', 'Headers', 'Request', 'Response', 'MessageEvent', ]); // https://websockets.spec.whatwg.org/ diff --git a/lib/internal/worker/io.js b/lib/internal/worker/io.js index 6e60ca373e0809..6a6e307a9e5008 100644 --- a/lib/internal/worker/io.js +++ b/lib/internal/worker/io.js @@ -20,7 +20,6 @@ const { } = primordials; const { - kEmptyObject, kEnumerableProperty, setOwnProperty, } = require('internal/util'); @@ -38,7 +37,6 @@ const { moveMessagePortToContext, receiveMessageOnPort: receiveMessageOnPort_, stopMessagePort, - checkMessagePort, DOMException, } = internalBinding('messaging'); const { @@ -59,25 +57,19 @@ const { const { inspect } = require('internal/util/inspect'); const { codes: { - ERR_INVALID_ARG_TYPE, ERR_INVALID_THIS, ERR_MISSING_ARGS, }, } = require('internal/errors'); -const kData = Symbol('kData'); const kHandle = Symbol('kHandle'); const kIncrementsPortRef = Symbol('kIncrementsPortRef'); -const kLastEventId = Symbol('kLastEventId'); const kName = Symbol('kName'); -const kOrigin = Symbol('kOrigin'); const kOnMessage = Symbol('kOnMessage'); const kOnMessageError = Symbol('kOnMessageError'); const kPort = Symbol('kPort'); -const kPorts = Symbol('kPorts'); const kWaitingStreams = Symbol('kWaitingStreams'); const kWritableCallbacks = Symbol('kWritableCallbacks'); -const kSource = Symbol('kSource'); const kStartedReading = Symbol('kStartedReading'); const kStdioWantsMoreDataCallback = Symbol('kStdioWantsMoreDataCallback'); const kCurrentlyReceivingPorts = @@ -93,6 +85,11 @@ const messageTypes = { LOAD_SCRIPT: 'loadScript', }; +let messageEvent; +function lazyMessageEvent() { + return messageEvent ??= require('internal/deps/undici/undici').MessageEvent; +} + // We have to mess with the MessagePort prototype a bit, so that a) we can make // it inherit from NodeEventTarget, even though it is a C++ class, and b) we do // not provide methods that are not present in the Browser and not documented @@ -119,95 +116,6 @@ MessagePort.prototype.hasRef = function() { return !!FunctionPrototypeCall(MessagePortPrototype.hasRef, this); }; -function validateMessagePort(port, name) { - if (!checkMessagePort(port)) - throw new ERR_INVALID_ARG_TYPE(name, 'MessagePort', port); -} - -function isMessageEvent(value) { - return value != null && kData in value; -} - -class MessageEvent extends Event { - constructor(type, { - data = null, - origin = '', - lastEventId = '', - source = null, - ports = [], - } = kEmptyObject) { - super(type); - this[kData] = data; - this[kOrigin] = `${origin}`; - this[kLastEventId] = `${lastEventId}`; - this[kSource] = source; - this[kPorts] = [...ports]; - - if (this[kSource] !== null) - validateMessagePort(this[kSource], 'init.source'); - for (let i = 0; i < this[kPorts].length; i++) - validateMessagePort(this[kPorts][i], `init.ports[${i}]`); - } -} - -ObjectDefineProperties(MessageEvent.prototype, { - data: { - __proto__: null, - get() { - if (!isMessageEvent(this)) - throw new ERR_INVALID_THIS('MessageEvent'); - return this[kData]; - }, - enumerable: true, - configurable: true, - set: undefined, - }, - origin: { - __proto__: null, - get() { - if (!isMessageEvent(this)) - throw new ERR_INVALID_THIS('MessageEvent'); - return this[kOrigin]; - }, - enumerable: true, - configurable: true, - set: undefined, - }, - lastEventId: { - __proto__: null, - get() { - if (!isMessageEvent(this)) - throw new ERR_INVALID_THIS('MessageEvent'); - return this[kLastEventId]; - }, - enumerable: true, - configurable: true, - set: undefined, - }, - source: { - __proto__: null, - get() { - if (!isMessageEvent(this)) - throw new ERR_INVALID_THIS('MessageEvent'); - return this[kSource]; - }, - enumerable: true, - configurable: true, - set: undefined, - }, - ports: { - __proto__: null, - get() { - if (!isMessageEvent(this)) - throw new ERR_INVALID_THIS('MessageEvent'); - return this[kPorts]; - }, - enumerable: true, - configurable: true, - set: undefined, - }, -}); - const originalCreateEvent = EventTarget.prototype[kCreateEvent]; ObjectDefineProperty( MessagePort.prototype, @@ -220,7 +128,7 @@ ObjectDefineProperty( } const ports = this[kCurrentlyReceivingPorts]; this[kCurrentlyReceivingPorts] = undefined; - return new MessageEvent(type, { data, ports }); + return new (lazyMessageEvent())(type, { data, ports }); }, configurable: false, writable: false, @@ -413,7 +321,7 @@ function receiveMessageOnPort(port) { } function onMessageEvent(type, data) { - this.dispatchEvent(new MessageEvent(type, { data })); + this.dispatchEvent(new (lazyMessageEvent())(type, { data })); } function isBroadcastChannel(value) { @@ -546,7 +454,6 @@ module.exports = { moveMessagePortToContext, MessagePort, MessageChannel, - MessageEvent, receiveMessageOnPort, setupPortReferencing, ReadableWorkerStdio, diff --git a/test/parallel/test-messageevent-brandcheck.js b/test/parallel/test-messageevent-brandcheck.js index 2174b3f7bbc94c..17f2b708cc5673 100644 --- a/test/parallel/test-messageevent-brandcheck.js +++ b/test/parallel/test-messageevent-brandcheck.js @@ -1,13 +1,8 @@ -// Flags: --expose-internals 'use strict'; require('../common'); const assert = require('assert'); -const { - MessageEvent, -} = require('internal/worker/io'); - [ 'data', 'origin', @@ -15,7 +10,5 @@ const { 'source', 'ports', ].forEach((i) => { - assert.throws(() => Reflect.get(MessageEvent.prototype, i, {}), { - code: 'ERR_INVALID_THIS', - }); + assert.throws(() => Reflect.get(MessageEvent.prototype, i, {}), TypeError); }); diff --git a/test/parallel/test-worker-message-event.js b/test/parallel/test-worker-message-event.js index 8ea08145a1d0a2..012bfc731fe7d1 100644 --- a/test/parallel/test-worker-message-event.js +++ b/test/parallel/test-worker-message-event.js @@ -61,31 +61,31 @@ const dummyPort = new MessageChannel().port1; assert.throws(() => { new MessageEvent('message', { source: 1 }); }, { - code: 'ERR_INVALID_ARG_TYPE', - message: /The "init\.source" property must be an instance of MessagePort/, + name: 'TypeError', + message: /Expected 1 to be an instance of MessagePort/, }); assert.throws(() => { new MessageEvent('message', { source: {} }); }, { - code: 'ERR_INVALID_ARG_TYPE', - message: /The "init\.source" property must be an instance of MessagePort/, + name: 'TypeError', + message: /Expected {} to be an instance of MessagePort/, }); assert.throws(() => { new MessageEvent('message', { ports: 0 }); }, { - message: /ports is not iterable/, + message: /Sequence: Value of type Number is not an Object/, }); assert.throws(() => { new MessageEvent('message', { ports: [ null ] }); }, { - code: 'ERR_INVALID_ARG_TYPE', - message: /The "init\.ports\[0\]" property must be an instance of MessagePort/, + name: 'TypeError', + message: /Expected null to be an instance of MessagePort/, }); assert.throws(() => { new MessageEvent('message', { ports: [ {} ] }); }, { - code: 'ERR_INVALID_ARG_TYPE', - message: /The "init\.ports\[0\]" property must be an instance of MessagePort/, + name: 'TypeError', + message: /Expected {} to be an instance of MessagePort/, }); }