diff --git a/lib/internal/blob.js b/lib/internal/blob.js index e42773a8d03dcc..ad8f9d7292da5a 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.json b/test/wpt/status/FileAPI/blob.json index a82a9cb0cfdb11..498e43cbc94bdf 100644 --- a/test/wpt/status/FileAPI/blob.json +++ b/test/wpt/status/FileAPI/blob.json @@ -4,14 +4,6 @@ }, "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.",