diff --git a/lib/web/fetch/headers.js b/lib/web/fetch/headers.js index cc4d138140b..d782d2a2793 100644 --- a/lib/web/fetch/headers.js +++ b/lib/web/fetch/headers.js @@ -451,7 +451,7 @@ class Headers { // 2. If init is given, then fill this with init. if (init !== undefined) { - init = webidl.converters.HeadersInit(init, 'Headers contructor', 'init') + init = webidl.converters.HeadersInit(init, 'Headers constructor', 'init') fill(this, init) } } diff --git a/lib/web/fetch/webidl.js b/lib/web/fetch/webidl.js index 23ba8f57df2..46850e16f05 100644 --- a/lib/web/fetch/webidl.js +++ b/lib/web/fetch/webidl.js @@ -345,12 +345,14 @@ webidl.recordConverter = function (keyConverter, valueConverter) { const keys = [...Object.getOwnPropertyNames(O), ...Object.getOwnPropertySymbols(O)] for (const key of keys) { + const keyName = webidl.util.Stringify(key) + // 1. Let typedKey be key converted to an IDL value of type K. - const typedKey = keyConverter(key, prefix, argument) + const typedKey = keyConverter(key, prefix, `Key ${keyName} in ${argument}`) // 2. Let value be ? Get(O, key). // 3. Let typedValue be value converted to an IDL value of type V. - const typedValue = valueConverter(O[key], prefix, argument) + const typedValue = valueConverter(O[key], prefix, `${argument}[${keyName}]`) // 4. Set result[typedKey] to typedValue. result[typedKey] = typedValue @@ -501,8 +503,14 @@ webidl.converters.DOMString = function (V, prefix, argument, opts) { // https://webidl.spec.whatwg.org/#es-ByteString webidl.converters.ByteString = function (V, prefix, argument) { // 1. Let x be ? ToString(V). - // Note: DOMString converter perform ? ToString(V) - const x = webidl.converters.DOMString(V, prefix, argument) + if (typeof V === 'symbol') { + throw webidl.errors.exception({ + header: prefix, + message: `${argument} is a symbol, which cannot be converted to a ByteString.` + }) + } + + const x = String(V) // 2. If the value of any element of x is greater than // 255, then throw a TypeError. diff --git a/test/fetch/headers.js b/test/fetch/headers.js index 38dd6b16886..02d500d6f80 100644 --- a/test/fetch/headers.js +++ b/test/fetch/headers.js @@ -26,7 +26,7 @@ test('Headers initialization', async (t) => { throws(() => new Headers(['undici', 'fetch', 'fetch']), TypeError) throws( () => new Headers([0, 1, 2]), - TypeError('Headers contructor: init[0] (0) is not iterable.') + TypeError('Headers constructor: init[0] (0) is not iterable.') ) }) @@ -41,7 +41,7 @@ test('Headers initialization', async (t) => { const init = ['undici', 'fetch', 'fetch', 'undici'] throws( () => new Headers(init), - TypeError('Headers contructor: init[0] ("undici") is not iterable.') + TypeError('Headers constructor: init[0] ("undici") is not iterable.') ) }) }) @@ -767,3 +767,16 @@ test('Invalid Symbol.iterators', (t) => { new Headers(obj) // eslint-disable-line no-new }, TypeError) }) + +// https://github.com/nodejs/undici/issues/3829 +test('Invalid key/value records passed to constructor (issue #3829)', (t) => { + assert.throws( + () => new Headers({ [Symbol('x-fake-header')]: '??' }), + new TypeError('Headers constructor: Key Symbol(x-fake-header) in init is a symbol, which cannot be converted to a ByteString.') + ) + + assert.throws( + () => new Headers({ 'x-fake-header': Symbol('why is this here?') }), + new TypeError('Headers constructor: init["x-fake-header"] is a symbol, which cannot be converted to a ByteString.') + ) +}) diff --git a/test/webidl/errors.js b/test/webidl/errors.js index c5406c35325..a1e0873a2f3 100644 --- a/test/webidl/errors.js +++ b/test/webidl/errors.js @@ -17,7 +17,7 @@ test('ByteString', (t) => { ]) { assert.throws( () => new Headers()[method](name, value), - new TypeError(`Headers.${method}: name is a symbol, which cannot be converted to a DOMString.`) + new TypeError(`Headers.${method}: name is a symbol, which cannot be converted to a ByteString.`) ) } })