Skip to content

Commit

Permalink
web: mark as uncloneable when possible
Browse files Browse the repository at this point in the history
This tells node that the marked instances from undici are not cloneable,
so that attempts to cloning those throw `DataCloneError`.
  • Loading branch information
jazelly committed Oct 10, 2024
1 parent 87d7ccf commit 325a719
Show file tree
Hide file tree
Showing 8 changed files with 30 additions and 7 deletions.
8 changes: 8 additions & 0 deletions lib/core/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const { IncomingMessage } = require('node:http')
const stream = require('node:stream')
const net = require('node:net')
const { Blob } = require('node:buffer')
const { markAsUncloneable } = require('node:worker_threads')
const nodeUtil = require('node:util')
const { stringify } = require('node:querystring')
const { EventEmitter: EE } = require('node:events')
Expand Down Expand Up @@ -816,6 +817,12 @@ function errorRequest (client, request, err) {
}
}

function maybeMarkAsUncloneable (target) {
if (markAsUncloneable !== undefined) {
markAsUncloneable(target)
}
}

const kEnumerableProperty = Object.create(null)
kEnumerableProperty.enumerable = true

Expand Down Expand Up @@ -875,6 +882,7 @@ module.exports = {
isFormDataLike,
serializePathWithQuery,
addAbortListener,
maybeMarkAsUncloneable,
isValidHTTPToken,
isValidHeaderValue,
isTokenCharCode,
Expand Down
4 changes: 3 additions & 1 deletion lib/web/eventsource/eventsource.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const { parseMIMEType } = require('../fetch/data-url')
const { createFastMessageEvent } = require('../websocket/events')
const { isNetworkError } = require('../fetch/response')
const { delay } = require('./util')
const { kEnumerableProperty } = require('../../core/util')
const { kEnumerableProperty, maybeMarkAsUncloneable } = require('../../core/util')
const { environmentSettingsObject } = require('../fetch/util')

let experimentalWarned = false
Expand Down Expand Up @@ -109,6 +109,8 @@ class EventSource extends EventTarget {
// 1. Let ev be a new EventSource object.
super()

maybeMarkAsUncloneable(this)

const prefix = 'EventSource constructor'
webidl.argumentLengthCheck(arguments, 1, prefix)

Expand Down
4 changes: 3 additions & 1 deletion lib/web/fetch/formdata.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const { iteratorMixin } = require('./util')
const { kEnumerableProperty } = require('../../core/util')
const { kEnumerableProperty, maybeMarkAsUncloneable } = require('../../core/util')
const { webidl } = require('./webidl')
const { File: NativeFile } = require('node:buffer')
const nodeUtil = require('node:util')
Expand All @@ -14,6 +14,8 @@ class FormData {
#state = []

constructor (form) {
maybeMarkAsUncloneable(this)

if (form !== undefined) {
throw webidl.errors.conversionFailed({
prefix: 'FormData constructor',
Expand Down
4 changes: 3 additions & 1 deletion lib/web/fetch/headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
'use strict'

const { kConstruct } = require('../../core/symbols')
const { kEnumerableProperty } = require('../../core/util')
const { kEnumerableProperty, maybeMarkAsUncloneable } = require('../../core/util')
const {
iteratorMixin,
isValidHeaderName,
Expand Down Expand Up @@ -189,6 +189,8 @@ class HeadersList {
headersMap

constructor (init) {
maybeMarkAsUncloneable(this)

if (init instanceof HeadersList) {
this.headersMap = new Map(init.headersMap)
this.sortedMap = init.sortedMap
Expand Down
4 changes: 3 additions & 1 deletion lib/web/fetch/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const {
requestCache,
requestDuplex
} = require('./constants')
const { kEnumerableProperty, normalizedMethodRecordsBase, normalizedMethodRecords } = util
const { kEnumerableProperty, maybeMarkAsUncloneable, normalizedMethodRecordsBase, normalizedMethodRecords } = util
const { webidl } = require('./webidl')
const { URLSerializer } = require('./data-url')
const { kConstruct } = require('../../core/symbols')
Expand Down Expand Up @@ -92,6 +92,8 @@ class Request {

// https://fetch.spec.whatwg.org/#dom-request
constructor (input, init = undefined) {
maybeMarkAsUncloneable(this)

if (input === kConstruct) {
return
}
Expand Down
4 changes: 3 additions & 1 deletion lib/web/fetch/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { Headers, HeadersList, fill, getHeadersGuard, setHeadersGuard, setHeaders
const { extractBody, cloneBody, mixinBody, hasFinalizationRegistry, streamRegistry, bodyUnusable } = require('./body')
const util = require('../../core/util')
const nodeUtil = require('node:util')
const { kEnumerableProperty } = util
const { kEnumerableProperty, maybeMarkAsUncloneable } = util
const {
isValidReasonPhrase,
isCancelled,
Expand Down Expand Up @@ -113,6 +113,8 @@ class Response {

// https://fetch.spec.whatwg.org/#dom-response
constructor (body = null, init = undefined) {
maybeMarkAsUncloneable(this)

if (body === kConstruct) {
return
}
Expand Down
5 changes: 4 additions & 1 deletion lib/web/websocket/events.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const { webidl } = require('../fetch/webidl')
const { kEnumerableProperty } = require('../../core/util')
const { kEnumerableProperty, maybeMarkAsUncloneable } = require('../../core/util')
const { kConstruct } = require('../../core/symbols')
const { MessagePort } = require('node:worker_threads')

Expand All @@ -14,6 +14,7 @@ class MessageEvent extends Event {
constructor (type, eventInitDict = {}) {
if (type === kConstruct) {
super(arguments[1], arguments[2])
maybeMarkAsUncloneable(this)
return
}

Expand All @@ -26,6 +27,7 @@ class MessageEvent extends Event {
super(type, eventInitDict)

this.#eventInit = eventInitDict
maybeMarkAsUncloneable(this)
}

get data () {
Expand Down Expand Up @@ -112,6 +114,7 @@ class CloseEvent extends Event {
super(type, eventInitDict)

this.#eventInit = eventInitDict
maybeMarkAsUncloneable(this)
}

get wasClean () {
Expand Down
4 changes: 3 additions & 1 deletion lib/web/websocket/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const {
} = require('./util')
const { establishWebSocketConnection, closeWebSocketConnection } = require('./connection')
const { ByteParser } = require('./receiver')
const { kEnumerableProperty } = require('../../core/util')
const { kEnumerableProperty, maybeMarkAsUncloneable } = require('../../core/util')
const { getGlobalDispatcher } = require('../../global')
const { types } = require('node:util')
const { ErrorEvent, CloseEvent, createFastMessageEvent } = require('./events')
Expand Down Expand Up @@ -100,6 +100,8 @@ class WebSocket extends EventTarget {
constructor (url, protocols = []) {
super()

maybeMarkAsUncloneable(this)

const prefix = 'WebSocket constructor'
webidl.argumentLengthCheck(arguments, 1, prefix)

Expand Down

0 comments on commit 325a719

Please sign in to comment.