diff --git a/lib/web/cache/cache.js b/lib/web/cache/cache.js index 597de52bb4a..bdfa5c87bbb 100644 --- a/lib/web/cache/cache.js +++ b/lib/web/cache/cache.js @@ -36,6 +36,7 @@ class Cache { webidl.illegalConstructor() } + webidl.util.markAsUncloneable(this) this.#relevantRequestResponseList = arguments[1] } diff --git a/lib/web/cache/cachestorage.js b/lib/web/cache/cachestorage.js index 3e35200b626..3b1604c872d 100644 --- a/lib/web/cache/cachestorage.js +++ b/lib/web/cache/cachestorage.js @@ -16,6 +16,8 @@ class CacheStorage { if (arguments[0] !== kConstruct) { webidl.illegalConstructor() } + + webidl.util.markAsUncloneable(this) } async match (request, options = {}) { diff --git a/lib/web/websocket/events.js b/lib/web/websocket/events.js index 6504149e2d2..f899c21d42b 100644 --- a/lib/web/websocket/events.js +++ b/lib/web/websocket/events.js @@ -145,6 +145,7 @@ class ErrorEvent extends Event { webidl.argumentLengthCheck(arguments, 1, prefix) super(type, eventInitDict) + webidl.util.markAsUncloneable(this) type = webidl.converters.DOMString(type, prefix, 'type') eventInitDict = webidl.converters.ErrorEventInit(eventInitDict ?? {}) diff --git a/test/node-platform-objects.js b/test/node-platform-objects.js index 358a418496f..19e2b01a507 100644 --- a/test/node-platform-objects.js +++ b/test/node-platform-objects.js @@ -3,20 +3,26 @@ const { tspl } = require('@matteo.collina/tspl') const { test } = require('node:test') const { markAsUncloneable } = require('node:worker_threads') -const { Response, Request, FormData, Headers, MessageEvent, CloseEvent, EventSource, WebSocket } = require('..') +const { Response, Request, FormData, Headers, ErrorEvent, MessageEvent, CloseEvent, EventSource, WebSocket } = require('..') +const { CacheStorage } = require('../lib/web/cache/cachestorage') +const { Cache } = require('../lib/web/cache/cache') +const { kConstruct } = require('../lib/core/symbols') -test('undici instances should be uncloneable if node exposes api', async (t) => { +test('unserializable web instances should be uncloneable if node exposes the api', (t) => { if (markAsUncloneable !== undefined) { - t = tspl(t, { plan: 8 }) + t = tspl(t, { plan: 11 }) const uncloneables = [ { Uncloneable: Response, brand: 'Response' }, { Uncloneable: Request, value: 'http://localhost', brand: 'Request' }, { Uncloneable: FormData, brand: 'FormData' }, - { Uncloneable: MessageEvent, value: 'message', brand: 'MessageEvent' }, - { Uncloneable: CloseEvent, value: 'dummy type', brand: 'CloseEvent' }, + { Uncloneable: MessageEvent, value: 'dummy event', brand: 'MessageEvent' }, + { Uncloneable: CloseEvent, value: 'dummy event', brand: 'CloseEvent' }, + { Uncloneable: ErrorEvent, value: 'dummy event', brand: 'ErrorEvent' }, { Uncloneable: EventSource, value: 'http://localhost', brand: 'EventSource' }, { Uncloneable: Headers, brand: 'Headers' }, - { Uncloneable: WebSocket, value: 'http://localhost', brand: 'WebSocket' } + { Uncloneable: WebSocket, value: 'http://localhost', brand: 'WebSocket' }, + { Uncloneable: Cache, value: kConstruct, brand: 'Cache' }, + { Uncloneable: CacheStorage, value: kConstruct, brand: 'CacheStorage' } ] uncloneables.forEach((platformEntity) => { t.throws(() => structuredClone(new platformEntity.Uncloneable(platformEntity.value)), diff --git a/types/webidl.d.ts b/types/webidl.d.ts index c42a2617fd2..29765c0db5b 100644 --- a/types/webidl.d.ts +++ b/types/webidl.d.ts @@ -82,6 +82,12 @@ interface WebidlUtil { * Stringifies {@param V} */ Stringify (V: any): string + + /** + * Mark a value as uncloneable for Node.js. + * This is only effective in some newer Node.js versions + */ + markAsUncloneable (V: any): void } interface WebidlConverters {