diff --git a/lib/internal/blob.js b/lib/internal/blob.js index e1b1dceabd629d..5059b651f467ca 100644 --- a/lib/internal/blob.js +++ b/lib/internal/blob.js @@ -1,7 +1,6 @@ 'use strict'; const { - ArrayFrom, MathMax, MathMin, ObjectDefineProperties, @@ -15,7 +14,6 @@ const { StringPrototypeSplit, StringPrototypeToLowerCase, Symbol, - SymbolIterator, SymbolToStringTag, Uint8Array, } = primordials; @@ -54,12 +52,15 @@ const { lazyDOMException, } = require('internal/util'); const { inspect } = require('internal/util/inspect'); -const { convertToInt } = require('internal/webidl'); +const { + converters, + convertToInt, + createSequenceConverter, +} = require('internal/webidl'); const { codes: { ERR_BUFFER_TOO_LARGE, - ERR_INVALID_ARG_TYPE, ERR_INVALID_ARG_VALUE, ERR_INVALID_STATE, ERR_INVALID_THIS, @@ -112,7 +113,6 @@ function getSource(source, endings) { if (isAnyArrayBuffer(source)) { source = new Uint8Array(source); } else if (!isArrayBufferView(source)) { - source = `${source}`; if (endings === 'native') source = RegExpPrototypeSymbolReplace(/\n|\r\n/g, source, EOL); source = enc.encode(source); @@ -126,6 +126,13 @@ function getSource(source, endings) { return [byteLength, new Uint8Array(slice)]; } +const sourcesConverter = createSequenceConverter((source, opts = kEmptyObject) => { + if (isBlob(source) || isAnyArrayBuffer(source) || isArrayBufferView(source)) { + return source; + } + return converters.DOMString(source, opts); +}); + class Blob { /** * @typedef {string|ArrayBuffer|ArrayBufferView|Blob} SourcePart @@ -142,11 +149,8 @@ class Blob { constructor(sources = [], options) { markTransferMode(this, true, false); - if (sources === null || - typeof sources[SymbolIterator] !== 'function' || - typeof sources === 'string') { - throw new ERR_INVALID_ARG_TYPE('sources', 'a sequence', sources); - } + const sources_ = sourcesConverter(sources); + validateDictionary(options, 'options'); let { endings = 'transparent', @@ -158,11 +162,11 @@ class Blob { throw new ERR_INVALID_ARG_VALUE('options.endings', endings); let length = 0; - const sources_ = ArrayFrom(sources, (source) => { - const { 0: len, 1: src } = getSource(source, endings); + for (let i = 0; i < sources_.length; ++i) { + const { 0: len, 1: src } = getSource(sources_[i], endings); length += len; - return src; - }); + sources_[i] = src; + } if (length > kMaxLength) throw new ERR_BUFFER_TOO_LARGE(kMaxLength); diff --git a/test/wpt/status/FileAPI/blob.cjs b/test/wpt/status/FileAPI/blob.cjs index b59756abc70121..99ec7dd22cea5f 100644 --- a/test/wpt/status/FileAPI/blob.cjs +++ b/test/wpt/status/FileAPI/blob.cjs @@ -25,14 +25,6 @@ module.exports = { }, 'Blob-constructor.any.js': { fail: { - expected: [ - 'blobParts not an object: boolean with Boolean.prototype[Symbol.iterator]', - 'blobParts not an object: number with Number.prototype[Symbol.iterator]', - 'blobParts not an object: BigInt with BigInt.prototype[Symbol.iterator]', - 'blobParts not an object: Symbol with Symbol.prototype[Symbol.iterator]', - 'Getters and value conversions should happen in order until an exception is thrown.', - 'Arguments should be evaluated from left to right.', - ], flaky: [ 'Passing typed arrays as elements of the blobParts array should work.', 'Passing a Float16Array as element of the blobParts array should work.',