summaryrefslogtreecommitdiff
path: root/ext/web/08_text_encoding.js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/web/08_text_encoding.js')
-rw-r--r--ext/web/08_text_encoding.js61
1 files changed, 35 insertions, 26 deletions
diff --git a/ext/web/08_text_encoding.js b/ext/web/08_text_encoding.js
index 4477d9b9e..bf4b33808 100644
--- a/ext/web/08_text_encoding.js
+++ b/ext/web/08_text_encoding.js
@@ -16,14 +16,14 @@
const ops = core.ops;
const webidl = window.__bootstrap.webidl;
const {
- ArrayBufferIsView,
- ObjectPrototypeIsPrototypeOf,
PromiseReject,
PromiseResolve,
StringPrototypeCharCodeAt,
StringPrototypeSlice,
TypedArrayPrototypeSubarray,
Uint8Array,
+ ObjectPrototypeIsPrototypeOf,
+ ArrayBufferIsView,
Uint32Array,
} = window.__bootstrap.primordials;
@@ -34,6 +34,8 @@
#fatal;
/** @type {boolean} */
#ignoreBOM;
+ /** @type {boolean} */
+ #utf8SinglePass;
/** @type {number | null} */
#rid = null;
@@ -56,6 +58,7 @@
this.#encoding = encoding;
this.#fatal = options.fatal;
this.#ignoreBOM = options.ignoreBOM;
+ this.#utf8SinglePass = encoding === "utf-8" && !options.fatal;
this[webidl.brand] = webidl.brand;
}
@@ -81,7 +84,7 @@
* @param {BufferSource} [input]
* @param {TextDecodeOptions} options
*/
- decode(input = new Uint8Array(), options = {}) {
+ decode(input = new Uint8Array(), options = undefined) {
webidl.assertBranded(this, TextDecoderPrototype);
const prefix = "Failed to execute 'decode' on 'TextDecoder'";
if (input !== undefined) {
@@ -91,40 +94,46 @@
allowShared: true,
});
}
- options = webidl.converters.TextDecodeOptions(options, {
- prefix,
- context: "Argument 2",
- });
+ let stream = false;
+ if (options !== undefined) {
+ options = webidl.converters.TextDecodeOptions(options, {
+ prefix,
+ context: "Argument 2",
+ });
+ stream = options.stream;
+ }
try {
- try {
- if (ArrayBufferIsView(input)) {
- input = new Uint8Array(
- input.buffer,
- input.byteOffset,
- input.byteLength,
- );
- } else {
- input = new Uint8Array(input);
- }
- } catch {
- // If the buffer is detached, just create a new empty Uint8Array.
- input = new Uint8Array();
- }
+ // Note from spec: implementations are strongly encouraged to use an implementation strategy that avoids this copy.
+ // When doing so they will have to make sure that changes to input do not affect future calls to decode().
if (
ObjectPrototypeIsPrototypeOf(
SharedArrayBuffer.prototype,
- input.buffer,
+ input || input.buffer,
)
) {
// We clone the data into a non-shared ArrayBuffer so we can pass it
// to Rust.
// `input` is now a Uint8Array, and calling the TypedArray constructor
// with a TypedArray argument copies the data.
- input = new Uint8Array(input);
+ if (ArrayBufferIsView(input)) {
+ input = new Uint8Array(
+ input.buffer,
+ input.byteOffset,
+ input.byteLength,
+ );
+ } else {
+ input = new Uint8Array(input);
+ }
}
- if (!options.stream && this.#rid === null) {
+ // Fast path for single pass encoding.
+ if (!stream && this.#rid === null) {
+ // Fast path for utf8 single pass encoding.
+ if (this.#utf8SinglePass) {
+ return ops.op_encoding_decode_utf8(input, this.#ignoreBOM);
+ }
+
return ops.op_encoding_decode_single(
input,
this.#encoding,
@@ -140,9 +149,9 @@
this.#ignoreBOM,
);
}
- return ops.op_encoding_decode(input, this.#rid, options.stream);
+ return ops.op_encoding_decode(input, this.#rid, stream);
} finally {
- if (!options.stream && this.#rid !== null) {
+ if (!stream && this.#rid !== null) {
core.close(this.#rid);
this.#rid = null;
}