Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 20 additions & 21 deletions lib/internal/encoding.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ const kHandle = Symbol('handle');
const kFlags = Symbol('flags');
const kEncoding = Symbol('encoding');
const kDecoder = Symbol('decoder');
const kEncoder = Symbol('encoder');
const kFatal = Symbol('kFatal');
const kUTF8FastPath = Symbol('kUTF8FastPath');
const kLatin1FastPath = Symbol('kLatin1FastPath');
Expand Down Expand Up @@ -61,11 +60,6 @@ const {

const { Buffer } = require('buffer');

function validateEncoder(obj) {
if (obj == null || obj[kEncoder] !== true)
throw new ERR_INVALID_THIS('TextEncoder');
}

function validateDecoder(obj) {
if (obj == null || obj[kDecoder] !== true)
throw new ERR_INVALID_THIS('TextDecoder');
Expand Down Expand Up @@ -338,45 +332,50 @@ function getEncodingFromLabel(label) {
return encodings.get(trimAsciiWhitespace(label.toLowerCase()));
}

let lazyInspect;

class TextEncoder {
constructor() {
this[kEncoder] = true;
#encoding = 'utf-8';

#encode(input) {
return encodeUtf8String(`${input}`);
}

#encodeInto(input, dest) {
encodeInto(input, dest);
// We need to read from the binding here since the buffer gets refreshed
// from the snapshot.
const { 0: read, 1: written } = encodeIntoResults;
return { read, written };
}

get encoding() {
validateEncoder(this);
return 'utf-8';
return this.#encoding;
}

encode(input = '') {
validateEncoder(this);
return encodeUtf8String(`${input}`);
return this.#encode(input);
}

encodeInto(src, dest) {
validateEncoder(this);
validateString(src, 'src');
if (!dest || !isUint8Array(dest))
throw new ERR_INVALID_ARG_TYPE('dest', 'Uint8Array', dest);

encodeInto(src, dest);
// We need to read from the binding here since the buffer gets refreshed
// from the snapshot.
const { 0: read, 1: written } = encodeIntoResults;
return { read, written };
return this.#encodeInto(src, dest);
}

[inspect](depth, opts) {
validateEncoder(this);
if (typeof depth === 'number' && depth < 0)
return this;
const ctor = getConstructorOf(this);
const obj = { __proto__: {
constructor: ctor === null ? TextEncoder : ctor,
} };
obj.encoding = this.encoding;
obj.encoding = this.#encoding;
// Lazy to avoid circular dependency
return require('internal/util/inspect').inspect(obj, opts);
lazyInspect ??= require('internal/util/inspect').inspect;
return lazyInspect(obj, opts);
}
}

Expand Down
10 changes: 7 additions & 3 deletions test/parallel/test-whatwg-encoding-custom-interop.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,8 @@ assert(TextEncoder);
const instance = new TextEncoder();

const expectedError = {
code: 'ERR_INVALID_THIS',
name: 'TypeError',
message: 'Value of "this" must be of type TextEncoder'
message: /from an object whose class did not declare it/,
};

inspectFn.call(instance, Infinity, {});
Expand All @@ -58,7 +57,12 @@ assert(TextEncoder);
const invalidThisArgs = [{}, [], true, 1, '', new TextDecoder()];
for (const i of invalidThisArgs) {
assert.throws(() => inspectFn.call(i, Infinity, {}), expectedError);
assert.throws(() => encodeFn.call(i), expectedError);
assert.throws(() => encodingGetter.call(i), expectedError);
}
for (const i of invalidThisArgs) {
assert.throws(() => encodeFn.call(i), {
name: 'TypeError',
message: 'Receiver must be an instance of class TextEncoder',
});
}
}
Loading