Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions lib/web/cookies/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const { Headers } = require('../fetch/headers')
function getCookies (headers) {
webidl.argumentLengthCheck(arguments, 1, 'getCookies')

webidl.brandCheck(headers, Headers, { strict: false })
webidl.brandCheckMultiple(headers, [Headers, globalThis.Headers])

const cookie = headers.get('cookie')

Expand All @@ -53,7 +53,7 @@ function getCookies (headers) {
* @returns {void}
*/
function deleteCookie (headers, name, attributes) {
webidl.brandCheck(headers, Headers, { strict: false })
webidl.brandCheckMultiple(headers, [Headers, globalThis.Headers])

const prefix = 'deleteCookie'
webidl.argumentLengthCheck(arguments, 2, prefix)
Expand All @@ -78,7 +78,7 @@ function deleteCookie (headers, name, attributes) {
function getSetCookies (headers) {
webidl.argumentLengthCheck(arguments, 1, 'getSetCookies')

webidl.brandCheck(headers, Headers, { strict: false })
webidl.brandCheckMultiple(headers, [Headers, globalThis.Headers])

const cookies = headers.getSetCookie()

Expand All @@ -97,7 +97,7 @@ function getSetCookies (headers) {
function setCookie (headers, cookie) {
webidl.argumentLengthCheck(arguments, 2, 'setCookie')

webidl.brandCheck(headers, Headers, { strict: false })
webidl.brandCheckMultiple(headers, [Headers, globalThis.Headers])

cookie = webidl.converters.Cookie(cookie)

Expand Down
30 changes: 18 additions & 12 deletions lib/web/fetch/webidl.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,24 @@ webidl.errors.invalidArgument = function (context) {

// https://webidl.spec.whatwg.org/#implements
webidl.brandCheck = function (V, I, opts) {
if (opts?.strict !== false) {
if (!(V instanceof I)) {
const err = new TypeError('Illegal invocation')
err.code = 'ERR_INVALID_THIS' // node compat.
throw err
}
} else {
if (V?.[Symbol.toStringTag] !== I.prototype[Symbol.toStringTag]) {
const err = new TypeError('Illegal invocation')
err.code = 'ERR_INVALID_THIS' // node compat.
throw err
}
if (opts?.strict !== false && !(V instanceof I)) {
const err = new TypeError('Illegal invocation')
err.code = 'ERR_INVALID_THIS' // node compat.
throw err
} else if (V?.[Symbol.toStringTag] !== I.prototype[Symbol.toStringTag]) {
// TODO(@KhafraDev): this check does not work properly on extended classes

const err = new TypeError('Illegal invocation')
err.code = 'ERR_INVALID_THIS' // node compat.
throw err
}
}

webidl.brandCheckMultiple = function (V, List) {
if (List.every((clazz) => !(V instanceof clazz))) {
const err = new TypeError('Illegal invocation')
err.code = 'ERR_INVALID_THIS' // node compat.
throw err
}
}

Expand Down
13 changes: 13 additions & 0 deletions test/cookie/global-headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,16 @@ describe('Using global Headers', async () => {
assert.equal(headers.get('Set-Cookie'), 'undici=setCookie')
})
})

describe('Headers check is not too lax', () => {
class Headers {}
Object.defineProperty(Headers.prototype, Symbol.toStringTag, {
value: 'Headers',
configurable: true
})

assert.throws(() => getCookies(new Headers()), { code: 'ERR_INVALID_THIS' })
assert.throws(() => getSetCookies(new Headers()), { code: 'ERR_INVALID_THIS' })
assert.throws(() => setCookie(new Headers(), { name: 'a', value: 'b' }), { code: 'ERR_INVALID_THIS' })
assert.throws(() => deleteCookie(new Headers(), 'name'), { code: 'ERR_INVALID_THIS' })
})
4 changes: 3 additions & 1 deletion types/webidl.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,9 @@ export interface Webidl {
* @description Performs a brand-check on {@param V} to ensure it is a
* {@param cls} object.
*/
brandCheck <Interface>(V: unknown, cls: Interface, opts?: { strict?: boolean }): asserts V is Interface
brandCheck <Interface extends new () => unknown>(V: unknown, cls: Interface, opts?: { strict?: boolean }): asserts V is Interface

brandCheckMultiple <Interfaces extends (new () => unknown)[]> (V: unknown, list: Interfaces): asserts V is Interfaces[number]

/**
* @see https://webidl.spec.whatwg.org/#es-sequence
Expand Down