diff --git a/lib/internal/webstreams/encoding.js b/lib/internal/webstreams/encoding.js index b95441e12e0cf1..b5533b4287b65a 100644 --- a/lib/internal/webstreams/encoding.js +++ b/lib/internal/webstreams/encoding.js @@ -4,7 +4,6 @@ const { ObjectDefineProperties, String, StringPrototypeCharCodeAt, - Symbol, Uint8Array, } = primordials; @@ -31,32 +30,19 @@ const { kEnumerableProperty, } = require('internal/util'); -const kHandle = Symbol('kHandle'); -const kTransform = Symbol('kTransform'); -const kType = Symbol('kType'); -const kPendingHighSurrogate = Symbol('kPendingHighSurrogate'); - /** * @typedef {import('./readablestream').ReadableStream} ReadableStream * @typedef {import('./writablestream').WritableStream} WritableStream */ -function isTextEncoderStream(value) { - return typeof value?.[kHandle] === 'object' && - value?.[kType] === 'TextEncoderStream'; -} - -function isTextDecoderStream(value) { - return typeof value?.[kHandle] === 'object' && - value?.[kType] === 'TextDecoderStream'; -} - class TextEncoderStream { + #pendingHighSurrogate = null; + #handle; + #transform; + constructor() { - this[kPendingHighSurrogate] = null; - this[kType] = 'TextEncoderStream'; - this[kHandle] = new TextEncoder(); - this[kTransform] = new TransformStream({ + this.#handle = new TextEncoder(); + this.#transform = new TransformStream({ transform: (chunk, controller) => { // https://encoding.spec.whatwg.org/#encode-and-enqueue-a-chunk chunk = String(chunk); @@ -64,9 +50,9 @@ class TextEncoderStream { for (let i = 0; i < chunk.length; i++) { const item = chunk[i]; const codeUnit = StringPrototypeCharCodeAt(item, 0); - if (this[kPendingHighSurrogate] !== null) { - const highSurrogate = this[kPendingHighSurrogate]; - this[kPendingHighSurrogate] = null; + if (this.#pendingHighSurrogate !== null) { + const highSurrogate = this.#pendingHighSurrogate; + this.#pendingHighSurrogate = null; if (0xDC00 <= codeUnit && codeUnit <= 0xDFFF) { finalChunk += highSurrogate + item; continue; @@ -74,7 +60,7 @@ class TextEncoderStream { finalChunk += '\uFFFD'; } if (0xD800 <= codeUnit && codeUnit <= 0xDBFF) { - this[kPendingHighSurrogate] = item; + this.#pendingHighSurrogate = item; continue; } if (0xDC00 <= codeUnit && codeUnit <= 0xDFFF) { @@ -84,13 +70,13 @@ class TextEncoderStream { finalChunk += item; } if (finalChunk) { - const value = this[kHandle].encode(finalChunk); + const value = this.#handle.encode(finalChunk); controller.enqueue(value); } }, flush: (controller) => { // https://encoding.spec.whatwg.org/#encode-and-flush - if (this[kPendingHighSurrogate] !== null) { + if (this.#pendingHighSurrogate !== null) { controller.enqueue(new Uint8Array([0xEF, 0xBF, 0xBD])); } }, @@ -102,9 +88,7 @@ class TextEncoderStream { * @type {string} */ get encoding() { - if (!isTextEncoderStream(this)) - throw new ERR_INVALID_THIS('TextEncoderStream'); - return this[kHandle].encoding; + return this.#handle.encoding; } /** @@ -112,9 +96,7 @@ class TextEncoderStream { * @type {ReadableStream} */ get readable() { - if (!isTextEncoderStream(this)) - throw new ERR_INVALID_THIS('TextEncoderStream'); - return this[kTransform].readable; + return this.#transform.readable; } /** @@ -122,23 +104,24 @@ class TextEncoderStream { * @type {WritableStream} */ get writable() { - if (!isTextEncoderStream(this)) - throw new ERR_INVALID_THIS('TextEncoderStream'); - return this[kTransform].writable; + return this.#transform.writable; } [kInspect](depth, options) { - if (!isTextEncoderStream(this)) + if (this == null) throw new ERR_INVALID_THIS('TextEncoderStream'); return customInspect(depth, options, 'TextEncoderStream', { - encoding: this[kHandle].encoding, - readable: this[kTransform].readable, - writable: this[kTransform].writable, + encoding: this.#handle.encoding, + readable: this.#transform.readable, + writable: this.#transform.writable, }); } } class TextDecoderStream { + #handle; + #transform; + /** * @param {string} [encoding] * @param {{ @@ -147,16 +130,15 @@ class TextDecoderStream { * }} [options] */ constructor(encoding = 'utf-8', options = kEmptyObject) { - this[kType] = 'TextDecoderStream'; - this[kHandle] = new TextDecoder(encoding, options); - this[kTransform] = new TransformStream({ + this.#handle = new TextDecoder(encoding, options); + this.#transform = new TransformStream({ transform: (chunk, controller) => { - const value = this[kHandle].decode(chunk, { stream: true }); + const value = this.#handle.decode(chunk, { stream: true }); if (value) controller.enqueue(value); }, flush: (controller) => { - const value = this[kHandle].decode(); + const value = this.#handle.decode(); if (value) controller.enqueue(value); controller.terminate(); @@ -169,9 +151,7 @@ class TextDecoderStream { * @type {string} */ get encoding() { - if (!isTextDecoderStream(this)) - throw new ERR_INVALID_THIS('TextDecoderStream'); - return this[kHandle].encoding; + return this.#handle.encoding; } /** @@ -179,9 +159,7 @@ class TextDecoderStream { * @type {boolean} */ get fatal() { - if (!isTextDecoderStream(this)) - throw new ERR_INVALID_THIS('TextDecoderStream'); - return this[kHandle].fatal; + return this.#handle.fatal; } /** @@ -189,9 +167,7 @@ class TextDecoderStream { * @type {boolean} */ get ignoreBOM() { - if (!isTextDecoderStream(this)) - throw new ERR_INVALID_THIS('TextDecoderStream'); - return this[kHandle].ignoreBOM; + return this.#handle.ignoreBOM; } /** @@ -199,9 +175,7 @@ class TextDecoderStream { * @type {ReadableStream} */ get readable() { - if (!isTextDecoderStream(this)) - throw new ERR_INVALID_THIS('TextDecoderStream'); - return this[kTransform].readable; + return this.#transform.readable; } /** @@ -209,20 +183,18 @@ class TextDecoderStream { * @type {WritableStream} */ get writable() { - if (!isTextDecoderStream(this)) - throw new ERR_INVALID_THIS('TextDecoderStream'); - return this[kTransform].writable; + return this.#transform.writable; } [kInspect](depth, options) { - if (!isTextDecoderStream(this)) + if (this == null) throw new ERR_INVALID_THIS('TextDecoderStream'); return customInspect(depth, options, 'TextDecoderStream', { - encoding: this[kHandle].encoding, - fatal: this[kHandle].fatal, - ignoreBOM: this[kHandle].ignoreBOM, - readable: this[kTransform].readable, - writable: this[kTransform].writable, + encoding: this.#handle.encoding, + fatal: this.#handle.fatal, + ignoreBOM: this.#handle.ignoreBOM, + readable: this.#transform.readable, + writable: this.#transform.writable, }); } } diff --git a/test/parallel/test-whatwg-webstreams-encoding.js b/test/parallel/test-whatwg-webstreams-encoding.js index 97061650496c0d..b2b18df73bf1fe 100644 --- a/test/parallel/test-whatwg-webstreams-encoding.js +++ b/test/parallel/test-whatwg-webstreams-encoding.js @@ -48,23 +48,28 @@ const kEuro = Buffer.from([0xe2, 0x82, 0xac]).toString(); assert.throws( () => Reflect.get(TextDecoderStream.prototype, 'encoding', {}), { - code: 'ERR_INVALID_THIS', + name: 'TypeError', + message: /Cannot read private member/, }); assert.throws( () => Reflect.get(TextDecoderStream.prototype, 'fatal', {}), { - code: 'ERR_INVALID_THIS', + name: 'TypeError', + message: /Cannot read private member/, }); assert.throws( () => Reflect.get(TextDecoderStream.prototype, 'ignoreBOM', {}), { - code: 'ERR_INVALID_THIS', + name: 'TypeError', + message: /Cannot read private member/, }); assert.throws( () => Reflect.get(TextDecoderStream.prototype, 'readable', {}), { - code: 'ERR_INVALID_THIS', + name: 'TypeError', + message: /Cannot read private member/, }); assert.throws( () => Reflect.get(TextDecoderStream.prototype, 'writable', {}), { - code: 'ERR_INVALID_THIS', + name: 'TypeError', + message: /Cannot read private member/, }); } @@ -89,14 +94,17 @@ const kEuro = Buffer.from([0xe2, 0x82, 0xac]).toString(); assert.throws( () => Reflect.get(TextEncoderStream.prototype, 'encoding', {}), { - code: 'ERR_INVALID_THIS', + name: 'TypeError', + message: /Cannot read private member/, }); assert.throws( () => Reflect.get(TextEncoderStream.prototype, 'readable', {}), { - code: 'ERR_INVALID_THIS', + name: 'TypeError', + message: /Cannot read private member/, }); assert.throws( () => Reflect.get(TextEncoderStream.prototype, 'writable', {}), { - code: 'ERR_INVALID_THIS', + name: 'TypeError', + message: /Cannot read private member/, }); }