diff --git a/lib/internal/blob.js b/lib/internal/blob.js index 69feb22c3304f0..82a708a88db875 100644 --- a/lib/internal/blob.js +++ b/lib/internal/blob.js @@ -61,8 +61,8 @@ const { } = require('internal/errors'); const { - validateObject, isUint32, + validateDictionary, } = require('internal/validators'); const kHandle = Symbol('kHandle'); @@ -138,17 +138,17 @@ class Blob { * }} [options] * @constructs {Blob} */ - constructor(sources = [], options = kEmptyObject) { + constructor(sources = [], options) { if (sources === null || typeof sources[SymbolIterator] !== 'function' || typeof sources === 'string') { throw new ERR_INVALID_ARG_TYPE('sources', 'a sequence', sources); } - validateObject(options, 'options'); + validateDictionary(options, 'options'); let { type = '', endings = 'transparent', - } = options; + } = options ?? kEmptyObject; endings = `${endings}`; if (endings !== 'transparent' && endings !== 'native') diff --git a/lib/internal/validators.js b/lib/internal/validators.js index 20b7486315cf1f..efb18fc43c0556 100644 --- a/lib/internal/validators.js +++ b/lib/internal/validators.js @@ -257,6 +257,25 @@ const validateObject = hideStackFrames( } }); +/** + * @callback validateDictionary - We are using the Web IDL Standard definition + * of "dictionary" here, which means any value + * whose Type is either Undefined, Null, or + * Object (which includes functions). + * @param {*} value + * @param {string} name + * @see https://webidl.spec.whatwg.org/#es-dictionary + * @see https://tc39.es/ecma262/#table-typeof-operator-results + */ + +/** @type {validateDictionary} */ +const validateDictionary = hideStackFrames( + (value, name) => { + if (value != null && typeof value !== 'object' && typeof value !== 'function') { + throw new ERR_INVALID_ARG_TYPE(name, 'a dictionary', value); + } + }); + /** * @callback validateArray * @param {*} value @@ -505,6 +524,7 @@ module.exports = { validateBooleanArray, validateBoolean, validateBuffer, + validateDictionary, validateEncoding, validateFunction, validateInt32, diff --git a/test/parallel/test-blob.js b/test/parallel/test-blob.js index 7bec9dbf69e7c5..588fc0bfff0d49 100644 --- a/test/parallel/test-blob.js +++ b/test/parallel/test-blob.js @@ -287,3 +287,32 @@ assert.throws(() => new Blob({}), { assert.strictEqual(blob.size, 28); assert.strictEqual(blob.type, ''); })().then(common.mustCall()); + +{ + // Testing the defaults + [undefined, null, Object.create(null), { type: undefined }, { + get type() {}, // eslint-disable-line getter-return + }].forEach((options) => { + assert.strictEqual( + new Blob([], options).type, + new Blob([]).type, + ); + }); + + Reflect.defineProperty(Object.prototype, 'type', { + __proto__: null, + configurable: true, + get: common.mustCall(() => 3, 7), + }); + + [{}, [], () => {}, Number, new Number(), new String(), new Boolean()].forEach( + (options) => { + assert.strictEqual(new Blob([], options).type, '3'); + }, + ); + [0, '', true, Symbol(), 0n].forEach((options) => { + assert.throws(() => new Blob([], options), { code: 'ERR_INVALID_ARG_TYPE' }); + }); + + delete Object.prototype.type; +}