mirror of
https://github.com/denoland/deno.git
synced 2025-01-21 13:00:36 -05:00
refactor(web): use encoding_rs for text encoding (#10844)
This commit removes all JS based text encoding / text decoding. Instead encoding now happens in Rust via encoding_rs (already in tree). This implementation retains stream support, but adds the last missing encodings. We are incredibly close to 100% WPT on text encoding now. This should reduce our baseline heap by quite a bit.
This commit is contained in:
parent
bb0c90cadb
commit
c73ef5fa14
27 changed files with 641 additions and 4705 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -783,8 +783,11 @@ dependencies = [
|
||||||
name = "deno_web"
|
name = "deno_web"
|
||||||
version = "0.38.1"
|
version = "0.38.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"base64 0.13.0",
|
||||||
"deno_core",
|
"deno_core",
|
||||||
|
"encoding_rs",
|
||||||
"futures",
|
"futures",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in worker "") Requires read access to "[WILDCARD]local_file.ts", run again with the --allow-read flag
|
error: Uncaught (in worker "") Requires read access to "[WILDCARD]local_file.ts", run again with the --allow-read flag
|
||||||
at blob:null/[WILDCARD]:1:0
|
at blob:null/[WILDCARD]:1:0
|
||||||
error: Uncaught (in promise) Error: Unhandled error event reached main worker.
|
error: Uncaught (in promise) Error: Unhandled error event reached main worker.
|
||||||
at Worker.#poll (deno:runtime/js/11_workers.js:245:23)
|
at Worker.#poll (deno:runtime/js/11_workers.js:243:23)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
||||||
at blob:null/[WILDCARD]:1:0
|
at blob:null/[WILDCARD]:1:0
|
||||||
error: Uncaught (in promise) Error: Unhandled error event reached main worker.
|
error: Uncaught (in promise) Error: Unhandled error event reached main worker.
|
||||||
at Worker.#poll (deno:runtime/js/11_workers.js:245:23)
|
at Worker.#poll (deno:runtime/js/11_workers.js:243:23)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in worker "") Requires read access to "[WILDCARD]local_file.ts", run again with the --allow-read flag
|
error: Uncaught (in worker "") Requires read access to "[WILDCARD]local_file.ts", run again with the --allow-read flag
|
||||||
at data:application/javascript;base64,[WILDCARD]:1:0
|
at data:application/javascript;base64,[WILDCARD]:1:0
|
||||||
error: Uncaught (in promise) Error: Unhandled error event reached main worker.
|
error: Uncaught (in promise) Error: Unhandled error event reached main worker.
|
||||||
at Worker.#poll (deno:runtime/js/11_workers.js:245:23)
|
at Worker.#poll (deno:runtime/js/11_workers.js:243:23)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
||||||
at data:application/javascript;base64,aW1wb3J0ICJodHRwczovL2V4YW1wbGUuY29tL3NvbWUvZmlsZS50cyI7:1:0
|
at data:application/javascript;base64,aW1wb3J0ICJodHRwczovL2V4YW1wbGUuY29tL3NvbWUvZmlsZS50cyI7:1:0
|
||||||
error: Uncaught (in promise) Error: Unhandled error event reached main worker.
|
error: Uncaught (in promise) Error: Unhandled error event reached main worker.
|
||||||
at Worker.#poll (deno:runtime/js/11_workers.js:245:23)
|
at Worker.#poll (deno:runtime/js/11_workers.js:243:23)
|
||||||
|
|
|
@ -3,4 +3,4 @@ await import("https://example.com/some/file.ts");
|
||||||
^
|
^
|
||||||
at async http://localhost:4545/cli/tests/workers/dynamic_remote.ts:2:1
|
at async http://localhost:4545/cli/tests/workers/dynamic_remote.ts:2:1
|
||||||
[WILDCARD]error: Uncaught (in promise) Error: Unhandled error event reached main worker.
|
[WILDCARD]error: Uncaught (in promise) Error: Unhandled error event reached main worker.
|
||||||
at Worker.#poll (deno:runtime/js/11_workers.js:245:23)
|
at Worker.#poll (deno:runtime/js/11_workers.js:243:23)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag
|
||||||
at http://localhost:4545/cli/tests/workers/static_remote.ts:2:0
|
at http://localhost:4545/cli/tests/workers/static_remote.ts:2:0
|
||||||
error: Uncaught (in promise) Error: Unhandled error event reached main worker.
|
error: Uncaught (in promise) Error: Unhandled error event reached main worker.
|
||||||
at Worker.#poll (deno:runtime/js/11_workers.js:245:23)
|
at Worker.#poll (deno:runtime/js/11_workers.js:243:23)
|
||||||
|
|
|
@ -36,6 +36,10 @@ pub fn type_error(message: impl Into<Cow<'static, str>>) -> AnyError {
|
||||||
custom_error("TypeError", message)
|
custom_error("TypeError", message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn range_error(message: impl Into<Cow<'static, str>>) -> AnyError {
|
||||||
|
custom_error("RangeError", message)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn invalid_hostname(hostname: &str) -> AnyError {
|
pub fn invalid_hostname(hostname: &str) -> AnyError {
|
||||||
type_error(format!("Invalid hostname: '{}'", hostname))
|
type_error(format!("Invalid hostname: '{}'", hostname))
|
||||||
}
|
}
|
||||||
|
|
11
core/lib.deno_core.d.ts
vendored
11
core/lib.deno_core.d.ts
vendored
|
@ -10,15 +10,15 @@ declare namespace Deno {
|
||||||
/** Call an op in Rust, and synchronously receive the result. */
|
/** Call an op in Rust, and synchronously receive the result. */
|
||||||
function opSync(
|
function opSync(
|
||||||
opName: string,
|
opName: string,
|
||||||
args?: any,
|
a?: any,
|
||||||
zeroCopy?: Uint8Array,
|
b?: any,
|
||||||
): any;
|
): any;
|
||||||
|
|
||||||
/** Call an op in Rust, and asynchronously receive the result. */
|
/** Call an op in Rust, and asynchronously receive the result. */
|
||||||
function opAsync(
|
function opAsync(
|
||||||
opName: string,
|
opName: string,
|
||||||
args?: any,
|
a?: any,
|
||||||
zeroCopy?: Uint8Array,
|
b?: any,
|
||||||
): Promise<any>;
|
): Promise<any>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,5 +38,8 @@ declare namespace Deno {
|
||||||
|
|
||||||
/** Get heap stats for current isolate/worker */
|
/** Get heap stats for current isolate/worker */
|
||||||
function heapStats(): Record<string, number>;
|
function heapStats(): Record<string, number>;
|
||||||
|
|
||||||
|
/** Encode a string to its Uint8Array representation. */
|
||||||
|
function encode(input: string): Uint8Array;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
/// <reference lib="esnext" />
|
/// <reference lib="esnext" />
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
((_window) => {
|
((window) => {
|
||||||
|
const core = window.Deno.core;
|
||||||
const webidl = globalThis.__bootstrap.webidl;
|
const webidl = globalThis.__bootstrap.webidl;
|
||||||
const { Blob, File, _byteSequence } = globalThis.__bootstrap.file;
|
const { Blob, File, _byteSequence } = globalThis.__bootstrap.file;
|
||||||
|
|
||||||
|
@ -240,8 +241,6 @@
|
||||||
|
|
||||||
webidl.mixinPairIterable("FormData", FormData, entryList, "name", "value");
|
webidl.mixinPairIterable("FormData", FormData, entryList, "name", "value");
|
||||||
|
|
||||||
const encoder = new TextEncoder();
|
|
||||||
|
|
||||||
class MultipartBuilder {
|
class MultipartBuilder {
|
||||||
/**
|
/**
|
||||||
* @param {FormData} formData
|
* @param {FormData} formData
|
||||||
|
@ -270,7 +269,7 @@
|
||||||
} else this.#writeField(name, value);
|
} else this.#writeField(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.chunks.push(encoder.encode(`\r\n--${this.boundary}--`));
|
this.chunks.push(core.encode(`\r\n--${this.boundary}--`));
|
||||||
|
|
||||||
let totalLength = 0;
|
let totalLength = 0;
|
||||||
for (const chunk of this.chunks) {
|
for (const chunk of this.chunks) {
|
||||||
|
@ -309,7 +308,7 @@
|
||||||
}
|
}
|
||||||
buf += `\r\n`;
|
buf += `\r\n`;
|
||||||
|
|
||||||
this.chunks.push(encoder.encode(buf));
|
this.chunks.push(core.encode(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -356,7 +355,7 @@
|
||||||
*/
|
*/
|
||||||
#writeField(field, value) {
|
#writeField(field, value) {
|
||||||
this.#writeFieldHeaders(field);
|
this.#writeFieldHeaders(field);
|
||||||
this.chunks.push(encoder.encode(this.#normalizeNewlines(value)));
|
this.chunks.push(core.encode(this.#normalizeNewlines(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -428,7 +427,6 @@
|
||||||
|
|
||||||
const LF = "\n".codePointAt(0);
|
const LF = "\n".codePointAt(0);
|
||||||
const CR = "\r".codePointAt(0);
|
const CR = "\r".codePointAt(0);
|
||||||
const decoder = new TextDecoder("utf-8");
|
|
||||||
|
|
||||||
class MultipartParser {
|
class MultipartParser {
|
||||||
/**
|
/**
|
||||||
|
@ -442,7 +440,7 @@
|
||||||
|
|
||||||
this.boundary = `--${boundary}`;
|
this.boundary = `--${boundary}`;
|
||||||
this.body = body;
|
this.body = body;
|
||||||
this.boundaryChars = encoder.encode(this.boundary);
|
this.boundaryChars = core.encode(this.boundary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -539,7 +537,7 @@
|
||||||
});
|
});
|
||||||
formData.append(name, blob, filename);
|
formData.append(name, blob, filename);
|
||||||
} else {
|
} else {
|
||||||
formData.append(name, decoder.decode(content));
|
formData.append(name, core.decode(content));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (state === 5 && isNewLine) {
|
} else if (state === 5 && isNewLine) {
|
||||||
|
|
|
@ -223,8 +223,6 @@
|
||||||
return Object.defineProperties(prototype.prototype, mixin);
|
return Object.defineProperties(prototype.prototype, mixin);
|
||||||
}
|
}
|
||||||
|
|
||||||
const decoder = new TextDecoder();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://fetch.spec.whatwg.org/#concept-body-package-data
|
* https://fetch.spec.whatwg.org/#concept-body-package-data
|
||||||
* @param {Uint8Array} bytes
|
* @param {Uint8Array} bytes
|
||||||
|
@ -263,14 +261,12 @@
|
||||||
throw new TypeError("Missing content type");
|
throw new TypeError("Missing content type");
|
||||||
}
|
}
|
||||||
case "JSON":
|
case "JSON":
|
||||||
return JSON.parse(decoder.decode(bytes));
|
return JSON.parse(core.decode(bytes));
|
||||||
case "text":
|
case "text":
|
||||||
return decoder.decode(bytes);
|
return core.decode(bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const encoder = new TextEncoder();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {BodyInit} object
|
* @param {BodyInit} object
|
||||||
* @returns {{body: InnerBody, contentType: string | null}}
|
* @returns {{body: InnerBody, contentType: string | null}}
|
||||||
|
@ -305,10 +301,10 @@
|
||||||
length = res.body.byteLength;
|
length = res.body.byteLength;
|
||||||
contentType = res.contentType;
|
contentType = res.contentType;
|
||||||
} else if (object instanceof URLSearchParams) {
|
} else if (object instanceof URLSearchParams) {
|
||||||
source = encoder.encode(object.toString());
|
source = core.encode(object.toString());
|
||||||
contentType = "application/x-www-form-urlencoded;charset=UTF-8";
|
contentType = "application/x-www-form-urlencoded;charset=UTF-8";
|
||||||
} else if (typeof object === "string") {
|
} else if (typeof object === "string") {
|
||||||
source = encoder.encode(object);
|
source = core.encode(object);
|
||||||
contentType = "text/plain;charset=UTF-8";
|
contentType = "text/plain;charset=UTF-8";
|
||||||
} else if (object instanceof ReadableStream) {
|
} else if (object instanceof ReadableStream) {
|
||||||
stream = object;
|
stream = object;
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
((window) => {
|
((window) => {
|
||||||
|
const core = window.Deno.core;
|
||||||
const webidl = window.__bootstrap.webidl;
|
const webidl = window.__bootstrap.webidl;
|
||||||
|
|
||||||
// TODO(lucacasonato): this needs to not be hardcoded and instead depend on
|
// TODO(lucacasonato): this needs to not be hardcoded and instead depend on
|
||||||
|
@ -85,9 +86,6 @@
|
||||||
return finalBytes;
|
return finalBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
const utf8Encoder = new TextEncoder();
|
|
||||||
const utf8Decoder = new TextDecoder();
|
|
||||||
|
|
||||||
/** @typedef {BufferSource | Blob | string} BlobPart */
|
/** @typedef {BufferSource | Blob | string} BlobPart */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -116,7 +114,7 @@
|
||||||
if (endings == "native") {
|
if (endings == "native") {
|
||||||
s = convertLineEndingsToNative(s);
|
s = convertLineEndingsToNative(s);
|
||||||
}
|
}
|
||||||
bytesArrays.push(utf8Encoder.encode(s));
|
bytesArrays.push(core.encode(s));
|
||||||
} else {
|
} else {
|
||||||
throw new TypeError("Unreachable code (invalild element type)");
|
throw new TypeError("Unreachable code (invalild element type)");
|
||||||
}
|
}
|
||||||
|
@ -276,7 +274,7 @@
|
||||||
async text() {
|
async text() {
|
||||||
webidl.assertBranded(this, Blob);
|
webidl.assertBranded(this, Blob);
|
||||||
const buffer = await this.arrayBuffer();
|
const buffer = await this.arrayBuffer();
|
||||||
return utf8Decoder.decode(buffer);
|
return core.decode(new Uint8Array(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
|
|
||||||
((window) => {
|
((window) => {
|
||||||
const webidl = window.__bootstrap.webidl;
|
const webidl = window.__bootstrap.webidl;
|
||||||
const { decode } = window.__bootstrap.encoding;
|
const { forgivingBase64Encode } = window.__bootstrap.infra;
|
||||||
|
const { decode, TextDecoder } = window.__bootstrap.encoding;
|
||||||
const { parseMimeType } = window.__bootstrap.mimesniff;
|
const { parseMimeType } = window.__bootstrap.mimesniff;
|
||||||
const base64 = window.__bootstrap.base64;
|
|
||||||
|
|
||||||
const state = Symbol("[[state]]");
|
const state = Symbol("[[state]]");
|
||||||
const result = Symbol("[[result]]");
|
const result = Symbol("[[result]]");
|
||||||
|
@ -168,7 +168,7 @@
|
||||||
case "DataUrl": {
|
case "DataUrl": {
|
||||||
const mediaType = blob.type || "application/octet-stream";
|
const mediaType = blob.type || "application/octet-stream";
|
||||||
this[result] = `data:${mediaType};base64,${
|
this[result] = `data:${mediaType};base64,${
|
||||||
base64.fromByteArray(bytes)
|
forgivingBase64Encode(bytes)
|
||||||
}`;
|
}`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
((window) => {
|
((window) => {
|
||||||
|
const core = Deno.core;
|
||||||
|
|
||||||
const ASCII_DIGIT = ["\u0030-\u0039"];
|
const ASCII_DIGIT = ["\u0030-\u0039"];
|
||||||
const ASCII_UPPER_ALPHA = ["\u0041-\u005A"];
|
const ASCII_UPPER_ALPHA = ["\u0041-\u005A"];
|
||||||
const ASCII_LOWER_ALPHA = ["\u0061-\u007A"];
|
const ASCII_LOWER_ALPHA = ["\u0061-\u007A"];
|
||||||
|
@ -178,6 +180,22 @@
|
||||||
return { result: input.substring(positionStart, position + 1), position };
|
return { result: input.substring(positionStart, position + 1), position };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Uint8Array} data
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function forgivingBase64Encode(data) {
|
||||||
|
return core.opSync("op_base64_encode", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} data
|
||||||
|
* @returns {Uint8Array}
|
||||||
|
*/
|
||||||
|
function forgivingBase64Decode(data) {
|
||||||
|
return core.opSync("op_base64_decode", data);
|
||||||
|
}
|
||||||
|
|
||||||
window.__bootstrap.infra = {
|
window.__bootstrap.infra = {
|
||||||
collectSequenceOfCodepoints,
|
collectSequenceOfCodepoints,
|
||||||
ASCII_DIGIT,
|
ASCII_DIGIT,
|
||||||
|
@ -199,5 +217,7 @@
|
||||||
byteUpperCase,
|
byteUpperCase,
|
||||||
byteLowerCase,
|
byteLowerCase,
|
||||||
collectHttpQuotedString,
|
collectHttpQuotedString,
|
||||||
|
forgivingBase64Encode,
|
||||||
|
forgivingBase64Decode,
|
||||||
};
|
};
|
||||||
})(globalThis);
|
})(globalThis);
|
||||||
|
|
62
extensions/web/05_base64.js
Normal file
62
extensions/web/05_base64.js
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
// @ts-check
|
||||||
|
/// <reference path="../webidl/internal.d.ts" />
|
||||||
|
/// <reference path="../web/internal.d.ts" />
|
||||||
|
/// <reference lib="esnext" />
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
((window) => {
|
||||||
|
const webidl = window.__bootstrap.webidl;
|
||||||
|
const {
|
||||||
|
forgivingBase64Encode,
|
||||||
|
forgivingBase64Decode,
|
||||||
|
} = window.__bootstrap.infra;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} data
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function atob(data) {
|
||||||
|
data = webidl.converters.DOMString(data, {
|
||||||
|
prefix: "Failed to execute 'atob'",
|
||||||
|
context: "Argument 1",
|
||||||
|
});
|
||||||
|
|
||||||
|
const uint8Array = forgivingBase64Decode(data);
|
||||||
|
const result = [...uint8Array]
|
||||||
|
.map((byte) => String.fromCharCode(byte))
|
||||||
|
.join("");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} data
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function btoa(data) {
|
||||||
|
const prefix = "Failed to execute 'btoa'";
|
||||||
|
webidl.requiredArguments(arguments.length, 1, { prefix });
|
||||||
|
data = webidl.converters.DOMString(data, {
|
||||||
|
prefix,
|
||||||
|
context: "Argument 1",
|
||||||
|
});
|
||||||
|
const byteArray = [...data].map((char) => {
|
||||||
|
const charCode = char.charCodeAt(0);
|
||||||
|
if (charCode > 0xff) {
|
||||||
|
throw new DOMException(
|
||||||
|
"The string to be encoded contains characters outside of the Latin1 range.",
|
||||||
|
"InvalidCharacterError",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return charCode;
|
||||||
|
});
|
||||||
|
return forgivingBase64Encode(Uint8Array.from(byteArray));
|
||||||
|
}
|
||||||
|
|
||||||
|
window.__bootstrap.base64 = {
|
||||||
|
atob,
|
||||||
|
btoa,
|
||||||
|
};
|
||||||
|
})(globalThis);
|
File diff suppressed because it is too large
Load diff
|
@ -14,7 +14,10 @@ repository = "https://github.com/denoland/deno"
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
base64 = "0.13.0"
|
||||||
deno_core = { version = "0.88.1", path = "../../core" }
|
deno_core = { version = "0.88.1", path = "../../core" }
|
||||||
|
encoding_rs = "0.8.28"
|
||||||
|
serde = "1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
futures = "0.3.15"
|
futures = "0.3.15"
|
||||||
|
|
7
extensions/web/internal.d.ts
vendored
7
extensions/web/internal.d.ts
vendored
|
@ -43,6 +43,8 @@ declare namespace globalThis {
|
||||||
result: string;
|
result: string;
|
||||||
position: number;
|
position: number;
|
||||||
};
|
};
|
||||||
|
forgivingBase64Encode(data: Uint8Array): string;
|
||||||
|
forgivingBase64Decode(data: string): Uint8Array;
|
||||||
};
|
};
|
||||||
|
|
||||||
declare namespace mimesniff {
|
declare namespace mimesniff {
|
||||||
|
@ -65,9 +67,8 @@ declare namespace globalThis {
|
||||||
};
|
};
|
||||||
|
|
||||||
declare var base64: {
|
declare var base64: {
|
||||||
byteLength(b64: string): number;
|
atob(data: string): string;
|
||||||
toByteArray(b64: string): Uint8Array;
|
btoa(data: string): string;
|
||||||
fromByteArray(uint8: Uint8Array): string;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
30
extensions/web/lib.deno_web.d.ts
vendored
30
extensions/web/lib.deno_web.d.ts
vendored
|
@ -177,20 +177,32 @@ declare function atob(s: string): string;
|
||||||
*/
|
*/
|
||||||
declare function btoa(s: string): string;
|
declare function btoa(s: string): string;
|
||||||
|
|
||||||
|
declare interface TextDecoderOptions {
|
||||||
|
fatal?: boolean;
|
||||||
|
ignoreBOM?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface TextDecodeOptions {
|
||||||
|
stream?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
declare class TextDecoder {
|
declare class TextDecoder {
|
||||||
|
constructor(label?: string, options?: TextDecoderOptions);
|
||||||
|
|
||||||
/** Returns encoding's name, lowercased. */
|
/** Returns encoding's name, lowercased. */
|
||||||
readonly encoding: string;
|
readonly encoding: string;
|
||||||
/** Returns `true` if error mode is "fatal", and `false` otherwise. */
|
/** Returns `true` if error mode is "fatal", and `false` otherwise. */
|
||||||
readonly fatal: boolean;
|
readonly fatal: boolean;
|
||||||
/** Returns `true` if ignore BOM flag is set, and `false` otherwise. */
|
/** Returns `true` if ignore BOM flag is set, and `false` otherwise. */
|
||||||
readonly ignoreBOM = false;
|
readonly ignoreBOM = false;
|
||||||
constructor(
|
|
||||||
label?: string,
|
|
||||||
options?: { fatal?: boolean; ignoreBOM?: boolean },
|
|
||||||
);
|
|
||||||
/** Returns the result of running encoding's decoder. */
|
/** Returns the result of running encoding's decoder. */
|
||||||
decode(input?: BufferSource, options?: { stream?: boolean }): string;
|
|
||||||
readonly [Symbol.toStringTag]: string;
|
decode(input?: BufferSource, options?: TextDecodeOptions): string;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare interface TextEncoderEncodeIntoResult {
|
||||||
|
read: number;
|
||||||
|
written: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare class TextEncoder {
|
declare class TextEncoder {
|
||||||
|
@ -198,11 +210,7 @@ declare class TextEncoder {
|
||||||
readonly encoding = "utf-8";
|
readonly encoding = "utf-8";
|
||||||
/** Returns the result of running UTF-8's encoder. */
|
/** Returns the result of running UTF-8's encoder. */
|
||||||
encode(input?: string): Uint8Array;
|
encode(input?: string): Uint8Array;
|
||||||
encodeInto(
|
encodeInto(input: string, dest: Uint8Array): TextEncoderEncodeIntoResult;
|
||||||
input: string,
|
|
||||||
dest: Uint8Array,
|
|
||||||
): { read: number; written: number };
|
|
||||||
readonly [Symbol.toStringTag]: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A controller object that allows you to abort one or more DOM requests as and
|
/** A controller object that allows you to abort one or more DOM requests as and
|
||||||
|
|
|
@ -1,10 +1,28 @@
|
||||||
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use deno_core::error::bad_resource_id;
|
||||||
|
use deno_core::error::range_error;
|
||||||
|
use deno_core::error::type_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::include_js_files;
|
use deno_core::include_js_files;
|
||||||
|
use deno_core::op_sync;
|
||||||
use deno_core::Extension;
|
use deno_core::Extension;
|
||||||
|
use deno_core::OpState;
|
||||||
|
use deno_core::Resource;
|
||||||
|
use deno_core::ResourceId;
|
||||||
|
use deno_core::ZeroCopyBuf;
|
||||||
|
use encoding_rs::CoderResult;
|
||||||
|
use encoding_rs::Decoder;
|
||||||
|
use encoding_rs::DecoderResult;
|
||||||
|
use encoding_rs::Encoding;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::usize;
|
||||||
|
|
||||||
/// Load and execute the javascript code.
|
/// Load and execute the javascript code.
|
||||||
pub fn init() -> Extension {
|
pub fn init() -> Extension {
|
||||||
|
@ -17,12 +35,235 @@ pub fn init() -> Extension {
|
||||||
"02_event.js",
|
"02_event.js",
|
||||||
"03_abort_signal.js",
|
"03_abort_signal.js",
|
||||||
"04_global_interfaces.js",
|
"04_global_interfaces.js",
|
||||||
|
"05_base64.js",
|
||||||
"08_text_encoding.js",
|
"08_text_encoding.js",
|
||||||
"12_location.js",
|
"12_location.js",
|
||||||
))
|
))
|
||||||
|
.ops(vec![
|
||||||
|
("op_base64_decode", op_sync(op_base64_decode)),
|
||||||
|
("op_base64_encode", op_sync(op_base64_encode)),
|
||||||
|
(
|
||||||
|
"op_encoding_normalize_label",
|
||||||
|
op_sync(op_encoding_normalize_label),
|
||||||
|
),
|
||||||
|
("op_encoding_new_decoder", op_sync(op_encoding_new_decoder)),
|
||||||
|
("op_encoding_decode", op_sync(op_encoding_decode)),
|
||||||
|
("op_encoding_encode_into", op_sync(op_encoding_encode_into)),
|
||||||
|
])
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn op_base64_decode(
|
||||||
|
_state: &mut OpState,
|
||||||
|
input: String,
|
||||||
|
_: (),
|
||||||
|
) -> Result<ZeroCopyBuf, AnyError> {
|
||||||
|
let mut input: &str = &input.replace(|c| char::is_ascii_whitespace(&c), "");
|
||||||
|
// "If the length of input divides by 4 leaving no remainder, then:
|
||||||
|
// if input ends with one or two U+003D EQUALS SIGN (=) characters,
|
||||||
|
// remove them from input."
|
||||||
|
if input.len() % 4 == 0 {
|
||||||
|
if input.ends_with("==") {
|
||||||
|
input = &input[..input.len() - 2]
|
||||||
|
} else if input.ends_with('=') {
|
||||||
|
input = &input[..input.len() - 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// "If the length of input divides by 4 leaving a remainder of 1,
|
||||||
|
// throw an InvalidCharacterError exception and abort these steps."
|
||||||
|
if input.len() % 4 == 1 {
|
||||||
|
return Err(
|
||||||
|
DomExceptionInvalidCharacterError::new("Failed to decode base64.").into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if input
|
||||||
|
.chars()
|
||||||
|
.any(|c| c != '+' && c != '/' && !c.is_alphanumeric())
|
||||||
|
{
|
||||||
|
return Err(
|
||||||
|
DomExceptionInvalidCharacterError::new(
|
||||||
|
"Failed to decode base64: invalid character",
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let cfg = base64::Config::new(base64::CharacterSet::Standard, true)
|
||||||
|
.decode_allow_trailing_bits(true);
|
||||||
|
let out = base64::decode_config(&input, cfg).map_err(|err| {
|
||||||
|
DomExceptionInvalidCharacterError::new(&format!(
|
||||||
|
"Failed to decode base64: {:?}",
|
||||||
|
err
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
Ok(ZeroCopyBuf::from(out))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn op_base64_encode(
|
||||||
|
_state: &mut OpState,
|
||||||
|
s: ZeroCopyBuf,
|
||||||
|
_: (),
|
||||||
|
) -> Result<String, AnyError> {
|
||||||
|
let cfg = base64::Config::new(base64::CharacterSet::Standard, true)
|
||||||
|
.decode_allow_trailing_bits(true);
|
||||||
|
let out = base64::encode_config(&s, cfg);
|
||||||
|
Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct DecoderOptions {
|
||||||
|
label: String,
|
||||||
|
ignore_bom: bool,
|
||||||
|
fatal: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn op_encoding_normalize_label(
|
||||||
|
_state: &mut OpState,
|
||||||
|
label: String,
|
||||||
|
_: (),
|
||||||
|
) -> Result<String, AnyError> {
|
||||||
|
let encoding = Encoding::for_label_no_replacement(label.as_bytes())
|
||||||
|
.ok_or_else(|| {
|
||||||
|
range_error(format!(
|
||||||
|
"The encoding label provided ('{}') is invalid.",
|
||||||
|
label
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
Ok(encoding.name().to_lowercase())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn op_encoding_new_decoder(
|
||||||
|
state: &mut OpState,
|
||||||
|
options: DecoderOptions,
|
||||||
|
_: (),
|
||||||
|
) -> Result<ResourceId, AnyError> {
|
||||||
|
let DecoderOptions {
|
||||||
|
label,
|
||||||
|
fatal,
|
||||||
|
ignore_bom,
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
let encoding = Encoding::for_label(label.as_bytes()).ok_or_else(|| {
|
||||||
|
range_error(format!(
|
||||||
|
"The encoding label provided ('{}') is invalid.",
|
||||||
|
label
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let decoder = if ignore_bom {
|
||||||
|
encoding.new_decoder_without_bom_handling()
|
||||||
|
} else {
|
||||||
|
encoding.new_decoder_with_bom_removal()
|
||||||
|
};
|
||||||
|
|
||||||
|
let rid = state.resource_table.add(TextDecoderResource {
|
||||||
|
decoder: RefCell::new(decoder),
|
||||||
|
fatal,
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(rid)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct DecodeOptions {
|
||||||
|
rid: ResourceId,
|
||||||
|
stream: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn op_encoding_decode(
|
||||||
|
state: &mut OpState,
|
||||||
|
data: ZeroCopyBuf,
|
||||||
|
options: DecodeOptions,
|
||||||
|
) -> Result<String, AnyError> {
|
||||||
|
let DecodeOptions { rid, stream } = options;
|
||||||
|
|
||||||
|
let resource = state
|
||||||
|
.resource_table
|
||||||
|
.get::<TextDecoderResource>(rid)
|
||||||
|
.ok_or_else(bad_resource_id)?;
|
||||||
|
|
||||||
|
let mut decoder = resource.decoder.borrow_mut();
|
||||||
|
let fatal = resource.fatal;
|
||||||
|
|
||||||
|
let max_buffer_length = if fatal {
|
||||||
|
decoder
|
||||||
|
.max_utf8_buffer_length_without_replacement(data.len())
|
||||||
|
.ok_or_else(|| range_error("Value too large to decode."))?
|
||||||
|
} else {
|
||||||
|
decoder
|
||||||
|
.max_utf8_buffer_length(data.len())
|
||||||
|
.ok_or_else(|| range_error("Value too large to decode."))?
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut output = String::with_capacity(max_buffer_length);
|
||||||
|
|
||||||
|
if fatal {
|
||||||
|
let (result, _) =
|
||||||
|
decoder.decode_to_string_without_replacement(&data, &mut output, !stream);
|
||||||
|
match result {
|
||||||
|
DecoderResult::InputEmpty => Ok(output),
|
||||||
|
DecoderResult::OutputFull => {
|
||||||
|
Err(range_error("Provided buffer too small."))
|
||||||
|
}
|
||||||
|
DecoderResult::Malformed(_, _) => {
|
||||||
|
Err(type_error("The encoded data is not valid."))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let (result, _, _) = decoder.decode_to_string(&data, &mut output, !stream);
|
||||||
|
match result {
|
||||||
|
CoderResult::InputEmpty => Ok(output),
|
||||||
|
CoderResult::OutputFull => Err(range_error("Provided buffer too small.")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TextDecoderResource {
|
||||||
|
decoder: RefCell<Decoder>,
|
||||||
|
fatal: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resource for TextDecoderResource {
|
||||||
|
fn name(&self) -> Cow<str> {
|
||||||
|
"textDecoder".into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct EncodeIntoResult {
|
||||||
|
read: usize,
|
||||||
|
written: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn op_encoding_encode_into(
|
||||||
|
_state: &mut OpState,
|
||||||
|
input: String,
|
||||||
|
mut buffer: ZeroCopyBuf,
|
||||||
|
) -> Result<EncodeIntoResult, AnyError> {
|
||||||
|
let dst: &mut [u8] = &mut buffer;
|
||||||
|
let mut read = 0;
|
||||||
|
let mut written = 0;
|
||||||
|
for char in input.chars() {
|
||||||
|
let len = char.len_utf8();
|
||||||
|
if dst.len() < written + len {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
char.encode_utf8(&mut dst[written..]);
|
||||||
|
written += len;
|
||||||
|
if char > '\u{FFFF}' {
|
||||||
|
read += 2
|
||||||
|
} else {
|
||||||
|
read += 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Ok(EncodeIntoResult { read, written })
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_declaration() -> PathBuf {
|
pub fn get_declaration() -> PathBuf {
|
||||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_web.d.ts")
|
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_web.d.ts")
|
||||||
}
|
}
|
||||||
|
@ -40,17 +281,39 @@ impl DomExceptionQuotaExceededError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DomExceptionInvalidCharacterError {
|
||||||
|
pub msg: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DomExceptionInvalidCharacterError {
|
||||||
|
pub fn new(msg: &str) -> Self {
|
||||||
|
DomExceptionInvalidCharacterError {
|
||||||
|
msg: msg.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for DomExceptionQuotaExceededError {
|
impl fmt::Display for DomExceptionQuotaExceededError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
f.pad(&self.msg)
|
f.pad(&self.msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl fmt::Display for DomExceptionInvalidCharacterError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.pad(&self.msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl std::error::Error for DomExceptionQuotaExceededError {}
|
impl std::error::Error for DomExceptionQuotaExceededError {}
|
||||||
|
|
||||||
pub fn get_quota_exceeded_error_class_name(
|
impl std::error::Error for DomExceptionInvalidCharacterError {}
|
||||||
e: &AnyError,
|
|
||||||
) -> Option<&'static str> {
|
pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
|
||||||
e.downcast_ref::<DomExceptionQuotaExceededError>()
|
e.downcast_ref::<DomExceptionQuotaExceededError>()
|
||||||
.map(|_| "DOMExceptionQuotaExceededError")
|
.map(|_| "DOMExceptionQuotaExceededError")
|
||||||
|
.or_else(|| {
|
||||||
|
e.downcast_ref::<DomExceptionInvalidCharacterError>()
|
||||||
|
.map(|_| "DOMExceptionInvalidCharacterError")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,8 +241,7 @@
|
||||||
sendTypedArray(new DataView(data));
|
sendTypedArray(new DataView(data));
|
||||||
} else {
|
} else {
|
||||||
const string = String(data);
|
const string = String(data);
|
||||||
const encoder = new TextEncoder();
|
const d = core.encode(string);
|
||||||
const d = encoder.encode(string);
|
|
||||||
this.#bufferedAmount += d.size;
|
this.#bufferedAmount += d.size;
|
||||||
core.opAsync("op_ws_send", {
|
core.opAsync("op_ws_send", {
|
||||||
rid: this.#rid,
|
rid: this.#rid,
|
||||||
|
@ -262,8 +261,7 @@
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const encoder = new TextEncoder();
|
if (reason && core.encode(reason).byteLength > 123) {
|
||||||
if (reason && encoder.encode(reason).byteLength > 123) {
|
|
||||||
throw new DOMException(
|
throw new DOMException(
|
||||||
"The close reason may not be longer than 123 bytes.",
|
"The close reason may not be longer than 123 bytes.",
|
||||||
"SyntaxError",
|
"SyntaxError",
|
||||||
|
|
|
@ -157,7 +157,7 @@ fn get_nix_error_class(error: &nix::Error) -> &'static str {
|
||||||
pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
|
pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
|
||||||
deno_core::error::get_custom_error_class(e)
|
deno_core::error::get_custom_error_class(e)
|
||||||
.or_else(|| deno_webgpu::error::get_error_class_name(e))
|
.or_else(|| deno_webgpu::error::get_error_class_name(e))
|
||||||
.or_else(|| deno_web::get_quota_exceeded_error_class_name(e))
|
.or_else(|| deno_web::get_error_class_name(e))
|
||||||
.or_else(|| deno_webstorage::get_not_supported_error_class_name(e))
|
.or_else(|| deno_webstorage::get_not_supported_error_class_name(e))
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
e.downcast_ref::<dlopen::Error>()
|
e.downcast_ref::<dlopen::Error>()
|
||||||
|
|
|
@ -38,8 +38,6 @@
|
||||||
return core.opAsync("op_host_get_message", id);
|
return core.opAsync("op_host_get_message", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
const decoder = new TextDecoder();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} permission
|
* @param {string} permission
|
||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
|
@ -166,7 +164,7 @@
|
||||||
|
|
||||||
this.#name = name;
|
this.#name = name;
|
||||||
const hasSourceCode = false;
|
const hasSourceCode = false;
|
||||||
const sourceCode = decoder.decode(new Uint8Array());
|
const sourceCode = core.decode(new Uint8Array());
|
||||||
|
|
||||||
if (
|
if (
|
||||||
specifier.startsWith("./") || specifier.startsWith("../") ||
|
specifier.startsWith("./") || specifier.startsWith("../") ||
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
((window) => {
|
((window) => {
|
||||||
|
const core = window.Deno.core;
|
||||||
const { open, openSync } = window.__bootstrap.files;
|
const { open, openSync } = window.__bootstrap.files;
|
||||||
const { readAll, readAllSync } = window.__bootstrap.io;
|
const { readAll, readAllSync } = window.__bootstrap.io;
|
||||||
|
|
||||||
|
@ -29,8 +30,7 @@
|
||||||
const file = openSync(path);
|
const file = openSync(path);
|
||||||
try {
|
try {
|
||||||
const contents = readAllSync(file);
|
const contents = readAllSync(file);
|
||||||
const decoder = new TextDecoder();
|
return core.decode(contents);
|
||||||
return decoder.decode(contents);
|
|
||||||
} finally {
|
} finally {
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,7 @@
|
||||||
const file = await open(path);
|
const file = await open(path);
|
||||||
try {
|
try {
|
||||||
const contents = await readAll(file);
|
const contents = await readAll(file);
|
||||||
const decoder = new TextDecoder();
|
return core.decode(contents);
|
||||||
return decoder.decode(contents);
|
|
||||||
} finally {
|
} finally {
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
const { isatty } = window.__bootstrap.tty;
|
const { isatty } = window.__bootstrap.tty;
|
||||||
const LF = "\n".charCodeAt(0);
|
const LF = "\n".charCodeAt(0);
|
||||||
const CR = "\r".charCodeAt(0);
|
const CR = "\r".charCodeAt(0);
|
||||||
const decoder = new TextDecoder();
|
|
||||||
const core = window.Deno.core;
|
const core = window.Deno.core;
|
||||||
|
|
||||||
function alert(message = "Alert") {
|
function alert(message = "Alert") {
|
||||||
|
@ -70,7 +69,7 @@
|
||||||
}
|
}
|
||||||
buf.push(c[0]);
|
buf.push(c[0]);
|
||||||
}
|
}
|
||||||
return decoder.decode(new Uint8Array(buf));
|
return core.decode(new Uint8Array(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
window.__bootstrap.prompt = {
|
window.__bootstrap.prompt = {
|
||||||
|
|
|
@ -16,6 +16,8 @@ delete Object.prototype.__proto__;
|
||||||
const errorStack = window.__bootstrap.errorStack;
|
const errorStack = window.__bootstrap.errorStack;
|
||||||
const os = window.__bootstrap.os;
|
const os = window.__bootstrap.os;
|
||||||
const timers = window.__bootstrap.timers;
|
const timers = window.__bootstrap.timers;
|
||||||
|
const base64 = window.__bootstrap.base64;
|
||||||
|
const encoding = window.__bootstrap.encoding;
|
||||||
const Console = window.__bootstrap.console.Console;
|
const Console = window.__bootstrap.console.Console;
|
||||||
const worker = window.__bootstrap.worker;
|
const worker = window.__bootstrap.worker;
|
||||||
const signals = window.__bootstrap.signals;
|
const signals = window.__bootstrap.signals;
|
||||||
|
@ -198,6 +200,12 @@ delete Object.prototype.__proto__;
|
||||||
return new DOMException(msg, "NotSupported");
|
return new DOMException(msg, "NotSupported");
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
core.registerErrorBuilder(
|
||||||
|
"DOMExceptionInvalidCharacterError",
|
||||||
|
function DOMExceptionInvalidCharacterError(msg) {
|
||||||
|
return new DOMException(msg, "InvalidCharacterError");
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Navigator {
|
class Navigator {
|
||||||
|
@ -277,8 +285,8 @@ delete Object.prototype.__proto__;
|
||||||
),
|
),
|
||||||
Request: util.nonEnumerable(fetch.Request),
|
Request: util.nonEnumerable(fetch.Request),
|
||||||
Response: util.nonEnumerable(fetch.Response),
|
Response: util.nonEnumerable(fetch.Response),
|
||||||
TextDecoder: util.nonEnumerable(TextDecoder),
|
TextDecoder: util.nonEnumerable(encoding.TextDecoder),
|
||||||
TextEncoder: util.nonEnumerable(TextEncoder),
|
TextEncoder: util.nonEnumerable(encoding.TextEncoder),
|
||||||
TransformStream: util.nonEnumerable(streams.TransformStream),
|
TransformStream: util.nonEnumerable(streams.TransformStream),
|
||||||
URL: util.nonEnumerable(url.URL),
|
URL: util.nonEnumerable(url.URL),
|
||||||
URLSearchParams: util.nonEnumerable(url.URLSearchParams),
|
URLSearchParams: util.nonEnumerable(url.URLSearchParams),
|
||||||
|
@ -295,8 +303,8 @@ delete Object.prototype.__proto__;
|
||||||
TransformStreamDefaultController: util.nonEnumerable(
|
TransformStreamDefaultController: util.nonEnumerable(
|
||||||
streams.TransformStreamDefaultController,
|
streams.TransformStreamDefaultController,
|
||||||
),
|
),
|
||||||
atob: util.writable(atob),
|
atob: util.writable(base64.atob),
|
||||||
btoa: util.writable(btoa),
|
btoa: util.writable(base64.btoa),
|
||||||
clearInterval: util.writable(timers.clearInterval),
|
clearInterval: util.writable(timers.clearInterval),
|
||||||
clearTimeout: util.writable(timers.clearTimeout),
|
clearTimeout: util.writable(timers.clearTimeout),
|
||||||
console: util.writable(
|
console: util.writable(
|
||||||
|
|
|
@ -187,18 +187,6 @@
|
||||||
"encodeInto() and a detached output buffer"
|
"encodeInto() and a detached output buffer"
|
||||||
],
|
],
|
||||||
"idlharness.any.html": [
|
"idlharness.any.html": [
|
||||||
"TextDecoder interface: existence and properties of interface object",
|
|
||||||
"TextDecoder interface: operation decode(optional BufferSource, optional TextDecodeOptions)",
|
|
||||||
"TextDecoder interface: attribute encoding",
|
|
||||||
"TextDecoder interface: attribute fatal",
|
|
||||||
"TextDecoder interface: attribute ignoreBOM",
|
|
||||||
"TextDecoder interface: new TextDecoder() must inherit property \"fatal\" with the proper type",
|
|
||||||
"TextDecoder interface: new TextDecoder() must inherit property \"ignoreBOM\" with the proper type",
|
|
||||||
"TextEncoder interface: existence and properties of interface object",
|
|
||||||
"TextEncoder interface: operation encode(optional USVString)",
|
|
||||||
"TextEncoder interface: operation encodeInto(USVString, Uint8Array)",
|
|
||||||
"TextEncoder interface: attribute encoding",
|
|
||||||
"TextEncoder interface: new TextEncoder() must inherit property \"encoding\" with the proper type",
|
|
||||||
"TextDecoderStream interface: existence and properties of interface object",
|
"TextDecoderStream interface: existence and properties of interface object",
|
||||||
"TextDecoderStream interface object length",
|
"TextDecoderStream interface object length",
|
||||||
"TextDecoderStream interface object name",
|
"TextDecoderStream interface object name",
|
||||||
|
@ -216,7 +204,7 @@
|
||||||
"TextEncoderStream interface: existence and properties of interface prototype object's @@unscopables property",
|
"TextEncoderStream interface: existence and properties of interface prototype object's @@unscopables property",
|
||||||
"TextEncoderStream interface: attribute encoding"
|
"TextEncoderStream interface: attribute encoding"
|
||||||
],
|
],
|
||||||
"iso-2022-jp-decoder.any.html": false,
|
"iso-2022-jp-decoder.any.html": true,
|
||||||
"legacy-mb-schinese": {
|
"legacy-mb-schinese": {
|
||||||
"gb18030": {
|
"gb18030": {
|
||||||
"gb18030-decoder.any.html": true
|
"gb18030-decoder.any.html": true
|
||||||
|
@ -237,11 +225,12 @@
|
||||||
"decode-utf8.any.html": false,
|
"decode-utf8.any.html": false,
|
||||||
"encode-bad-chunks.any.html": false,
|
"encode-bad-chunks.any.html": false,
|
||||||
"encode-utf8.any.html": false,
|
"encode-utf8.any.html": false,
|
||||||
"readable-writable-properties.any.html": false
|
"readable-writable-properties.any.html": false,
|
||||||
|
"realms.window.html": false
|
||||||
},
|
},
|
||||||
"textdecoder-arguments.any.html": true,
|
"textdecoder-arguments.any.html": true,
|
||||||
"textdecoder-byte-order-marks.any.html": true,
|
"textdecoder-byte-order-marks.any.html": true,
|
||||||
"textdecoder-copy.any.html": false,
|
"textdecoder-copy.any.html": true,
|
||||||
"textdecoder-fatal-single-byte.any.html?1-1000": true,
|
"textdecoder-fatal-single-byte.any.html?1-1000": true,
|
||||||
"textdecoder-fatal-single-byte.any.html?1001-2000": true,
|
"textdecoder-fatal-single-byte.any.html?1001-2000": true,
|
||||||
"textdecoder-fatal-single-byte.any.html?2001-3000": true,
|
"textdecoder-fatal-single-byte.any.html?2001-3000": true,
|
||||||
|
@ -250,46 +239,23 @@
|
||||||
"textdecoder-fatal-single-byte.any.html?5001-6000": true,
|
"textdecoder-fatal-single-byte.any.html?5001-6000": true,
|
||||||
"textdecoder-fatal-single-byte.any.html?6001-7000": true,
|
"textdecoder-fatal-single-byte.any.html?6001-7000": true,
|
||||||
"textdecoder-fatal-single-byte.any.html?7001-last": true,
|
"textdecoder-fatal-single-byte.any.html?7001-last": true,
|
||||||
"textdecoder-fatal-streaming.any.html": [
|
"textdecoder-fatal-streaming.any.html": true,
|
||||||
"Fatal flag, streaming cases"
|
|
||||||
],
|
|
||||||
"textdecoder-fatal.any.html": true,
|
"textdecoder-fatal.any.html": true,
|
||||||
"textdecoder-ignorebom.any.html": true,
|
"textdecoder-ignorebom.any.html": true,
|
||||||
"textdecoder-labels.any.html": [
|
"textdecoder-labels.any.html": [
|
||||||
"cseucpkdfmtjapanese => EUC-JP",
|
"unicode11utf8 => UTF-8",
|
||||||
"euc-jp => EUC-JP",
|
"unicode20utf8 => UTF-8",
|
||||||
"x-euc-jp => EUC-JP",
|
"x-unicode20utf8 => UTF-8",
|
||||||
"csiso2022jp => ISO-2022-JP",
|
"unicodefffe => UTF-16BE",
|
||||||
"iso-2022-jp => ISO-2022-JP",
|
"csunicode => UTF-16LE",
|
||||||
"csshiftjis => Shift_JIS",
|
"iso-10646-ucs-2 => UTF-16LE",
|
||||||
"ms932 => Shift_JIS",
|
"ucs-2 => UTF-16LE",
|
||||||
"ms_kanji => Shift_JIS",
|
"unicode => UTF-16LE",
|
||||||
"shift-jis => Shift_JIS",
|
"unicodefeff => UTF-16LE"
|
||||||
"shift_jis => Shift_JIS",
|
|
||||||
"sjis => Shift_JIS",
|
|
||||||
"windows-31j => Shift_JIS",
|
|
||||||
"x-sjis => Shift_JIS",
|
|
||||||
"cseuckr => EUC-KR",
|
|
||||||
"csksc56011987 => EUC-KR",
|
|
||||||
"euc-kr => EUC-KR",
|
|
||||||
"iso-ir-149 => EUC-KR",
|
|
||||||
"korean => EUC-KR",
|
|
||||||
"ks_c_5601-1987 => EUC-KR",
|
|
||||||
"ks_c_5601-1989 => EUC-KR",
|
|
||||||
"ksc5601 => EUC-KR",
|
|
||||||
"ksc_5601 => EUC-KR",
|
|
||||||
"windows-949 => EUC-KR",
|
|
||||||
"x-user-defined => x-user-defined"
|
|
||||||
],
|
],
|
||||||
"textdecoder-streaming.any.html": true,
|
"textdecoder-streaming.any.html": true,
|
||||||
"textdecoder-utf16-surrogates.any.html": true,
|
"textdecoder-utf16-surrogates.any.html": true,
|
||||||
"textencoder-constructor-non-utf.any.html": [
|
"textencoder-constructor-non-utf.any.html": true,
|
||||||
"Encoding argument supported for decode: EUC-JP",
|
|
||||||
"Encoding argument supported for decode: ISO-2022-JP",
|
|
||||||
"Encoding argument supported for decode: Shift_JIS",
|
|
||||||
"Encoding argument supported for decode: EUC-KR",
|
|
||||||
"Encoding argument supported for decode: x-user-defined"
|
|
||||||
],
|
|
||||||
"textencoder-utf16-surrogates.any.html": true,
|
"textencoder-utf16-surrogates.any.html": true,
|
||||||
"unsupported-encodings.any.html": false
|
"unsupported-encodings.any.html": false
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Reference in a new issue