From 9d652f42ebd96c8200f6b6befb88d199a2ed8665 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Thu, 9 Nov 2023 12:09:17 +0100 Subject: [PATCH] stream: treat compression web stream format per its WebIDL definition PR-URL: https://github.com/nodejs/node/pull/50631 Reviewed-By: James M Snell Reviewed-By: Matteo Collina --- lib/internal/crypto/webidl.js | 41 ++++---------------------- lib/internal/webidl.js | 40 ++++++++++++++++++++++++- lib/internal/webstreams/compression.js | 24 ++++++++++----- test/wpt/status/compression.json | 14 --------- 4 files changed, 60 insertions(+), 59 deletions(-) diff --git a/lib/internal/crypto/webidl.js b/lib/internal/crypto/webidl.js index 61a4cfe4330703..326d520b844d23 100644 --- a/lib/internal/crypto/webidl.js +++ b/lib/internal/crypto/webidl.js @@ -19,20 +19,22 @@ const { MathTrunc, Number, NumberIsFinite, - ObjectAssign, ObjectPrototypeIsPrototypeOf, SafeArrayIterator, - SafeSet, String, SymbolIterator, TypedArrayPrototypeGetBuffer, TypedArrayPrototypeGetSymbolToStringTag, - TypeError, globalThis: { SharedArrayBuffer, }, } = primordials; +const { + makeException, + createEnumConverter, +} = require('internal/webidl'); + const { kEmptyObject, setOwnProperty, @@ -40,23 +42,6 @@ const { const { CryptoKey } = require('internal/crypto/webcrypto'); const { getDataViewOrTypedArrayBuffer } = require('internal/crypto/util'); -function codedTypeError(message, errorProperties = kEmptyObject) { - // eslint-disable-next-line no-restricted-syntax - const err = new TypeError(message); - ObjectAssign(err, errorProperties); - return err; -} - -function makeException(message, opts = kEmptyObject) { - const prefix = opts.prefix ? opts.prefix + ': ' : ''; - const context = opts.context?.length === 0 ? - '' : (opts.context ?? 'Value') + ' '; - return codedTypeError( - `${prefix}${context}${message}`, - { code: opts.code || 'ERR_INVALID_ARG_TYPE' }, - ); -} - // https://tc39.es/ecma262/#sec-tonumber function toNumber(value, opts = kEmptyObject) { switch (typeof value) { @@ -308,22 +293,6 @@ function createDictionaryConverter(name, dictionaries) { }; } -function createEnumConverter(name, values) { - const E = new SafeSet(values); - - return function(V, opts = kEmptyObject) { - const S = String(V); - - if (!E.has(S)) { - throw makeException( - `value '${S}' is not a valid enum value of type ${name}.`, - { __proto__: null, ...opts, code: 'ERR_INVALID_ARG_VALUE' }); - } - - return S; - }; -} - function createSequenceConverter(converter) { return function(V, opts = kEmptyObject) { if (type(V) !== 'Object') { diff --git a/lib/internal/webidl.js b/lib/internal/webidl.js index 67c01418f167f7..eeb0f35586a2ed 100644 --- a/lib/internal/webidl.js +++ b/lib/internal/webidl.js @@ -10,7 +10,10 @@ const { NumberIsNaN, NumberMAX_SAFE_INTEGER, NumberMIN_SAFE_INTEGER, + ObjectAssign, + SafeSet, String, + TypeError, } = primordials; const { @@ -173,8 +176,43 @@ converters.DOMString = function DOMString(V) { return String(V); }; +function codedTypeError(message, errorProperties = kEmptyObject) { + // eslint-disable-next-line no-restricted-syntax + const err = new TypeError(message); + ObjectAssign(err, errorProperties); + return err; +} + +function makeException(message, opts = kEmptyObject) { + const prefix = opts.prefix ? opts.prefix + ': ' : ''; + const context = opts.context?.length === 0 ? + '' : (opts.context ?? 'Value') + ' '; + return codedTypeError( + `${prefix}${context}${message}`, + { code: opts.code || 'ERR_INVALID_ARG_TYPE' }, + ); +} + +function createEnumConverter(name, values) { + const E = new SafeSet(values); + + return function(V, opts = kEmptyObject) { + const S = String(V); + + if (!E.has(S)) { + throw makeException( + `value '${S}' is not a valid enum value of type ${name}.`, + { __proto__: null, ...opts, code: 'ERR_INVALID_ARG_VALUE' }); + } + + return S; + }; +} + module.exports = { + converters, convertToInt, + createEnumConverter, evenRound, - converters, + makeException, }; diff --git a/lib/internal/webstreams/compression.js b/lib/internal/webstreams/compression.js index d912959e29fd23..32f3f9b4605032 100644 --- a/lib/internal/webstreams/compression.js +++ b/lib/internal/webstreams/compression.js @@ -4,10 +4,6 @@ const { ObjectDefineProperties, } = primordials; -const { - codes: { ERR_INVALID_ARG_VALUE }, -} = require('internal/errors'); - const { newReadableWritablePairFromDuplex, } = require('internal/webstreams/adapters'); @@ -19,12 +15,20 @@ const { kEnumerableProperty, } = require('internal/util'); +const { createEnumConverter } = require('internal/webidl'); + let zlib; function lazyZlib() { zlib ??= require('zlib'); return zlib; } +const formatConverter = createEnumConverter('CompressionFormat', [ + 'deflate', + 'deflate-raw', + 'gzip', +]); + /** * @typedef {import('./readablestream').ReadableStream} ReadableStream * @typedef {import('./writablestream').WritableStream} WritableStream @@ -38,6 +42,10 @@ class CompressionStream { * @param {'deflate'|'deflate-raw'|'gzip'} format */ constructor(format) { + format = formatConverter(format, { + prefix: "Failed to construct 'CompressionStream'", + context: '1st argument', + }); switch (format) { case 'deflate': this.#handle = lazyZlib().createDeflate(); @@ -48,8 +56,6 @@ class CompressionStream { case 'gzip': this.#handle = lazyZlib().createGzip(); break; - default: - throw new ERR_INVALID_ARG_VALUE('format', format); } this.#transform = newReadableWritablePairFromDuplex(this.#handle); } @@ -86,6 +92,10 @@ class DecompressionStream { * @param {'deflate'|'deflate-raw'|'gzip'} format */ constructor(format) { + format = formatConverter(format, { + prefix: "Failed to construct 'DecompressionStream'", + context: '1st argument', + }); switch (format) { case 'deflate': this.#handle = lazyZlib().createInflate(); @@ -96,8 +106,6 @@ class DecompressionStream { case 'gzip': this.#handle = lazyZlib().createGunzip(); break; - default: - throw new ERR_INVALID_ARG_VALUE('format', format); } this.#transform = newReadableWritablePairFromDuplex(this.#handle); } diff --git a/test/wpt/status/compression.json b/test/wpt/status/compression.json index 8c8535c15815e4..cf979345ea87cb 100644 --- a/test/wpt/status/compression.json +++ b/test/wpt/status/compression.json @@ -2,26 +2,12 @@ "compression-bad-chunks.tentative.any.js": { "skip": "Execution \"hangs\", ArrayBuffer and TypedArray is not accepted and throws, instead of rejects during writer.write" }, - "compression-constructor-error.tentative.any.js": { - "fail": { - "expected": [ - "non-string input should cause the constructor to throw" - ] - } - }, "decompression-bad-chunks.tentative.any.js": { "skip": "Execution \"hangs\", ArrayBuffer and TypedArray is not accepted and throws, instead of rejects during writer.write" }, "decompression-buffersource.tentative.any.js": { "skip": "ArrayBuffer and TypedArray is not accepted and throws, instead of rejects during writer.write" }, - "decompression-constructor-error.tentative.any.js": { - "fail": { - "expected": [ - "non-string input should cause the constructor to throw" - ] - } - }, "compression-with-detach.tentative.window.js": { "requires": ["crypto"] },