diff --git a/lib/web/fetch/webidl.js b/lib/web/fetch/webidl.js index 9db13d07df7..d3cc4791550 100644 --- a/lib/web/fetch/webidl.js +++ b/lib/web/fetch/webidl.js @@ -354,12 +354,9 @@ webidl.interfaceConverter = function (i) { webidl.dictionaryConverter = function (converters) { return (dictionary, prefix, argument) => { - const type = webidl.util.Type(dictionary) const dict = {} - if (type === 'Null' || type === 'Undefined') { - return dict - } else if (type !== 'Object') { + if (dictionary != null && webidl.util.Type(dictionary) !== 'Object') { throw webidl.errors.exception({ header: prefix, message: `Expected ${dictionary} to be one of: Null, Undefined, Object.` @@ -370,7 +367,7 @@ webidl.dictionaryConverter = function (converters) { const { key, defaultValue, required, converter } = options if (required === true) { - if (!Object.hasOwn(dictionary, key)) { + if (dictionary == null || !Object.hasOwn(dictionary, key)) { throw webidl.errors.exception({ header: prefix, message: `Missing required key "${key}".` @@ -378,13 +375,13 @@ webidl.dictionaryConverter = function (converters) { } } - let value = dictionary[key] - const hasDefault = Object.hasOwn(options, 'defaultValue') + let value = dictionary?.[key] + const hasDefault = defaultValue !== undefined // Only use defaultValue if value is undefined and // a defaultValue options was provided. - if (hasDefault && value !== null) { - value ??= defaultValue() + if (hasDefault && value === undefined) { + value = defaultValue() } // A key can be optional and have no default value. diff --git a/test/webidl/converters.js b/test/webidl/converters.js index e88a54a48b6..ccc376a7ab9 100644 --- a/test/webidl/converters.js +++ b/test/webidl/converters.js @@ -76,6 +76,51 @@ describe('webidl.dictionaryConverter', () => { converter({ Key: 'this key was required!' }, 'converter', 'converter') }) }) + + test('null and undefined still populates defaultValue(s)', () => { + const dict = webidl.dictionaryConverter([ + { + key: 'key', + converter: webidl.converters.any, + defaultValue: () => 3 + } + ]) + + assert.deepStrictEqual(dict(null), { key: 3 }) + assert.deepStrictEqual(dict(undefined), { key: 3 }) + }) + + test('null and undefined throw a webidl TypeError with a required key', () => { + const dict = webidl.dictionaryConverter([ + { + key: 'key', + converter: webidl.converters.any, + required: true + } + ]) + + assert.throws(() => dict(null, 'prefix'), new TypeError('prefix: Missing required key "key".')) + assert.throws(() => dict(undefined, 'prefix'), new TypeError('prefix: Missing required key "key".')) + }) + + test('Object type works for functions and regex (etc.)', () => { + const dict = webidl.dictionaryConverter([ + { + key: 'key', + converter: webidl.converters.any, + required: true + } + ]) + + function obj () {} + obj.key = 1 + + const obj2 = / / + obj2.key = 1 + + assert.deepStrictEqual(dict(obj), { key: 1 }) + assert.deepStrictEqual(dict(obj2), { key: 1 }) + }) }) test('ArrayBuffer', () => {