diff --git a/Cargo.lock b/Cargo.lock index 8ceec13013..7703b7d4df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -772,6 +772,9 @@ version = "0.8.1" dependencies = [ "deno_bench_util", "deno_core", + "deno_url", + "deno_web", + "deno_webidl", "tokio", ] diff --git a/extensions/broadcast_channel/01_broadcast_channel.js b/extensions/broadcast_channel/01_broadcast_channel.js index 17a3fb42b3..42112c014d 100644 --- a/extensions/broadcast_channel/01_broadcast_channel.js +++ b/extensions/broadcast_channel/01_broadcast_channel.js @@ -8,6 +8,7 @@ const core = window.Deno.core; const webidl = window.__bootstrap.webidl; const { setTarget } = window.__bootstrap.event; + const { DOMException } = window.__bootstrap.domException; const { ArrayPrototypeIndexOf, ArrayPrototypeSplice, diff --git a/extensions/crypto/01_crypto.js b/extensions/crypto/01_crypto.js index e8ae65ef30..754e292f7d 100644 --- a/extensions/crypto/01_crypto.js +++ b/extensions/crypto/01_crypto.js @@ -4,6 +4,7 @@ ((window) => { const core = window.Deno.core; const webidl = window.__bootstrap.webidl; + const { DOMException } = window.__bootstrap.domException; const supportedAlgorithms = { "digest": { diff --git a/extensions/fetch/26_fetch.js b/extensions/fetch/26_fetch.js index d1fd1e9b36..e1e01c8035 100644 --- a/extensions/fetch/26_fetch.js +++ b/extensions/fetch/26_fetch.js @@ -26,6 +26,7 @@ abortedNetworkError, } = window.__bootstrap.fetch; const abortSignal = window.__bootstrap.abortSignal; + const { DOMException } = window.__bootstrap.domException; const REQUEST_BODY_HEADER_NAMES = [ "content-encoding", diff --git a/extensions/timers/02_performance.js b/extensions/timers/02_performance.js index bca98fdbd1..baa1676a29 100644 --- a/extensions/timers/02_performance.js +++ b/extensions/timers/02_performance.js @@ -4,6 +4,8 @@ ((window) => { const { webidl, structuredClone } = window.__bootstrap; const { opNow } = window.__bootstrap.timers; + const { DOMException } = window.__bootstrap.domException; + const illegalConstructorKey = Symbol("illegalConstructorKey"); const customInspect = Symbol.for("Deno.customInspect"); let performanceEntries = []; diff --git a/extensions/timers/Cargo.toml b/extensions/timers/Cargo.toml index bdd04b9335..ae754a9537 100644 --- a/extensions/timers/Cargo.toml +++ b/extensions/timers/Cargo.toml @@ -19,6 +19,9 @@ tokio = { version = "1.7.1", features = ["full"] } [dev-dependencies] deno_bench_util = { version = "0.4.0", path = "../../bench_util" } +deno_url = { version = "0.10.1", path = "../url" } +deno_web = { version = "0.41.1", path = "../web" } +deno_webidl = { version = "0.10.1", path = "../webidl" } [[bench]] name = "timers_ops" diff --git a/extensions/timers/benches/timers_ops.rs b/extensions/timers/benches/timers_ops.rs index e31fe31ace..c463efbfeb 100644 --- a/extensions/timers/benches/timers_ops.rs +++ b/extensions/timers/benches/timers_ops.rs @@ -3,9 +3,13 @@ use deno_core::Extension; use deno_bench_util::bench_or_profile; use deno_bench_util::bencher::{benchmark_group, Bencher}; use deno_bench_util::{bench_js_async, bench_js_sync}; +use deno_web::BlobUrlStore; fn setup() -> Vec { vec![ + deno_webidl::init(), + deno_url::init(), + deno_web::init(BlobUrlStore::default(), None), deno_timers::init::(), Extension::builder() .js(vec![ diff --git a/extensions/web/00_infra.js b/extensions/web/00_infra.js index 07c1ef41b9..7c065bcd3a 100644 --- a/extensions/web/00_infra.js +++ b/extensions/web/00_infra.js @@ -1,6 +1,7 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. // @ts-check +/// /// /// /// @@ -9,6 +10,22 @@ ((window) => { const core = Deno.core; + const { + RegExp, + ArrayPrototypeMap, + StringPrototypeCharCodeAt, + NumberPrototypeToString, + StringPrototypePadStart, + TypeError, + ArrayPrototypeJoin, + StringPrototypeCharAt, + StringPrototypeSlice, + String, + StringPrototypeReplace, + StringPrototypeToUpperCase, + StringPrototypeToLowerCase, + StringPrototypeSubstring, + } = window.__bootstrap.primordials; const ASCII_DIGIT = ["\u0030-\u0039"]; const ASCII_UPPER_ALPHA = ["\u0041-\u005A"]; @@ -73,18 +90,31 @@ * @returns {string} */ function regexMatcher(chars) { - const matchers = chars.map((char) => { + const matchers = ArrayPrototypeMap(chars, (char) => { if (char.length === 1) { - return `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}`; + const a = StringPrototypePadStart( + NumberPrototypeToString(StringPrototypeCharCodeAt(char, 0), 16), + 4, + "0", + ); + return `\\u${a}`; } else if (char.length === 3 && char[1] === "-") { - return `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}-\\u${ - char.charCodeAt(2).toString(16).padStart(4, "0") - }`; + const a = StringPrototypePadStart( + NumberPrototypeToString(StringPrototypeCharCodeAt(char, 0), 16), + 4, + "0", + ); + const b = StringPrototypePadStart( + NumberPrototypeToString(StringPrototypeCharCodeAt(char, 2), 16), + 4, + "0", + ); + return `\\u${a}-\\u${b}`; } else { throw TypeError("unreachable"); } }); - return matchers.join(""); + return ArrayPrototypeJoin(matchers, ""); } /** @@ -97,11 +127,11 @@ function collectSequenceOfCodepoints(input, position, condition) { const start = position; for ( - let c = input.charAt(position); + let c = StringPrototypeCharAt(input, position); position < input.length && condition(c); - c = input.charAt(++position) + c = StringPrototypeCharAt(input, ++position) ); - return { result: input.slice(start, position), position }; + return { result: StringPrototypeSlice(input, start, position), position }; } /** @@ -109,9 +139,13 @@ * @returns {string} */ function byteUpperCase(s) { - return String(s).replace(/[a-z]/g, function byteUpperCaseReplace(c) { - return c.toUpperCase(); - }); + return StringPrototypeReplace( + String(s), + /[a-z]/g, + function byteUpperCaseReplace(c) { + return StringPrototypeToUpperCase(c); + }, + ); } /** @@ -119,9 +153,13 @@ * @returns {string} */ function byteLowerCase(s) { - return String(s).replace(/[A-Z]/g, function byteUpperCaseReplace(c) { - return c.toLowerCase(); - }); + return StringPrototypeReplace( + String(s), + /[A-Z]/g, + function byteUpperCaseReplace(c) { + return StringPrototypeToLowerCase(c); + }, + ); } /** @@ -137,7 +175,7 @@ // 2. let value = ""; // 3. - if (input[position] !== "\u0022") throw new Error('must be "'); + if (input[position] !== "\u0022") throw new TypeError('must be "'); // 4. position++; // 5. @@ -169,7 +207,7 @@ position++; } else { // 5.6. // 5.6.1 - if (quoteOrBackslash !== "\u0022") throw new Error('must be "'); + if (quoteOrBackslash !== "\u0022") throw new TypeError('must be "'); // 5.6.2 break; } @@ -177,7 +215,10 @@ // 6. if (extractValue) return { result: value, position }; // 7. - return { result: input.substring(positionStart, position + 1), position }; + return { + result: StringPrototypeSubstring(input, positionStart, position + 1), + position, + }; } /** diff --git a/extensions/web/01_dom_exception.js b/extensions/web/01_dom_exception.js index e4bcb9fbaa..6c3c95f387 100644 --- a/extensions/web/01_dom_exception.js +++ b/extensions/web/01_dom_exception.js @@ -1,6 +1,7 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. // @ts-check +/// /// /// /// @@ -9,9 +10,10 @@ "use strict"; ((window) => { + const { ObjectDefineProperty, ObjectEntries } = + window.__bootstrap.primordials; const webidl = window.__bootstrap.webidl; - const { defineProperty } = Object; // Defined in WebIDL 4.3. // https://heycam.github.io/webidl/#idl-DOMException const INDEX_SIZE_ERR = 1; @@ -108,7 +110,7 @@ webidl.configurePrototype(DOMException); for ( - const [key, value] of Object.entries({ + const [key, value] of ObjectEntries({ INDEX_SIZE_ERR, DOMSTRING_SIZE_ERR, HIERARCHY_REQUEST_ERR, @@ -137,10 +139,9 @@ }) ) { const desc = { value, enumerable: true }; - defineProperty(DOMException, key, desc); - defineProperty(DOMException.prototype, key, desc); + ObjectDefineProperty(DOMException, key, desc); + ObjectDefineProperty(DOMException.prototype, key, desc); } - window.DOMException = DOMException; - defineProperty(window, "DOMException", { enumerable: false }); + window.__bootstrap.domException = { DOMException }; })(this); diff --git a/extensions/web/01_mimesniff.js b/extensions/web/01_mimesniff.js index b42dd14095..360d1ffe49 100644 --- a/extensions/web/01_mimesniff.js +++ b/extensions/web/01_mimesniff.js @@ -1,6 +1,7 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. // @ts-check +/// /// /// /// @@ -8,6 +9,15 @@ "use strict"; ((window) => { + const { + ArrayPrototypeIncludes, + Map, + MapPrototypeHas, + MapPrototypeSet, + RegExpPrototypeTest, + StringPrototypeReplaceAll, + StringPrototypeToLowerCase, + } = window.__bootstrap.primordials; const { collectSequenceOfCodepoints, HTTP_WHITESPACE, @@ -31,8 +41,8 @@ */ function parseMimeType(input) { // 1. - input = input.replaceAll(HTTP_WHITESPACE_PREFIX_RE, ""); - input = input.replaceAll(HTTP_WHITESPACE_SUFFIX_RE, ""); + input = StringPrototypeReplaceAll(input, HTTP_WHITESPACE_PREFIX_RE, ""); + input = StringPrototypeReplaceAll(input, HTTP_WHITESPACE_SUFFIX_RE, ""); // 2. let position = 0; @@ -48,7 +58,9 @@ position = res1.position; // 4. - if (type === "" || !HTTP_TOKEN_CODE_POINT_RE.test(type)) return null; + if (type === "" || !RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, type)) { + return null; + } // 5. if (position >= endOfInput) return null; @@ -66,15 +78,19 @@ position = res2.position; // 8. - subtype = subtype.replaceAll(HTTP_WHITESPACE_SUFFIX_RE, ""); + subtype = StringPrototypeReplaceAll(subtype, HTTP_WHITESPACE_SUFFIX_RE, ""); // 9. - if (subtype === "" || !HTTP_TOKEN_CODE_POINT_RE.test(subtype)) return null; + if ( + subtype === "" || !RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, subtype) + ) { + return null; + } // 10. const mimeType = { - type: type.toLowerCase(), - subtype: subtype.toLowerCase(), + type: StringPrototypeToLowerCase(type), + subtype: StringPrototypeToLowerCase(subtype), /** @type {Map} */ parameters: new Map(), }; @@ -88,7 +104,7 @@ const res1 = collectSequenceOfCodepoints( input, position, - (c) => HTTP_WHITESPACE.includes(c), + (c) => ArrayPrototypeIncludes(HTTP_WHITESPACE, c), ); position = res1.position; @@ -102,7 +118,7 @@ position = res2.position; // 11.4. - parameterName = parameterName.toLowerCase(); + parameterName = StringPrototypeToLowerCase(parameterName); // 11.5. if (position < endOfInput) { @@ -136,7 +152,8 @@ position = res.position; // 11.9.2. - parameterValue = parameterValue.replaceAll( + parameterValue = StringPrototypeReplaceAll( + parameterValue, HTTP_WHITESPACE_SUFFIX_RE, "", ); @@ -147,11 +164,15 @@ // 11.10. if ( - parameterName !== "" && HTTP_TOKEN_CODE_POINT_RE.test(parameterName) && - HTTP_QUOTED_STRING_TOKEN_POINT_RE.test(parameterValue) && - !mimeType.parameters.has(parameterName) + parameterName !== "" && + RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, parameterName) && + RegExpPrototypeTest( + HTTP_QUOTED_STRING_TOKEN_POINT_RE, + parameterValue, + ) && + !MapPrototypeHas(mimeType.parameters, parameterName) ) { - mimeType.parameters.set(parameterName, parameterValue); + MapPrototypeSet(mimeType.parameters, parameterName, parameterValue); } } @@ -176,9 +197,9 @@ for (const param of mimeType.parameters) { serialization += `;${param[0]}=`; let value = param[1]; - if (!HTTP_TOKEN_CODE_POINT_RE.test(value)) { - value = value.replaceAll("\\", "\\\\"); - value = value.replaceAll('"', '\\"'); + if (!RegExpPrototypeTest(HTTP_TOKEN_CODE_POINT_RE, value)) { + value = StringPrototypeReplaceAll(value, "\\", "\\\\"); + value = StringPrototypeReplaceAll(value, '"', '\\"'); value = `"${value}"`; } serialization += value; diff --git a/extensions/web/02_event.js b/extensions/web/02_event.js index 081869efdf..3fed3127ec 100644 --- a/extensions/web/02_event.js +++ b/extensions/web/02_event.js @@ -8,6 +8,7 @@ ((window) => { const webidl = window.__bootstrap.webidl; + const { DOMException } = window.__bootstrap.domException; // accessors for non runtime visible data diff --git a/extensions/web/02_structured_clone.js b/extensions/web/02_structured_clone.js index 2170095d9d..265d89247d 100644 --- a/extensions/web/02_structured_clone.js +++ b/extensions/web/02_structured_clone.js @@ -9,6 +9,7 @@ ((window) => { const core = window.Deno.core; + const { DOMException } = window.__bootstrap.domException; const objectCloneMemo = new WeakMap(); diff --git a/extensions/web/05_base64.js b/extensions/web/05_base64.js index 4c51d88f15..f0490f240b 100644 --- a/extensions/web/05_base64.js +++ b/extensions/web/05_base64.js @@ -13,6 +13,7 @@ forgivingBase64Encode, forgivingBase64Decode, } = window.__bootstrap.infra; + const { DOMException } = window.__bootstrap.domException; /** * @param {string} data diff --git a/extensions/web/06_streams.js b/extensions/web/06_streams.js index d26a1a4126..79403442aa 100644 --- a/extensions/web/06_streams.js +++ b/extensions/web/06_streams.js @@ -9,6 +9,7 @@ ((window) => { const webidl = window.__bootstrap.webidl; + const { DOMException } = window.__bootstrap.domException; class AssertionError extends Error { constructor(msg) { diff --git a/extensions/web/10_filereader.js b/extensions/web/10_filereader.js index b8bb6172af..161ce6ed35 100644 --- a/extensions/web/10_filereader.js +++ b/extensions/web/10_filereader.js @@ -16,6 +16,7 @@ const { forgivingBase64Encode } = window.__bootstrap.infra; const { decode, TextDecoder } = window.__bootstrap.encoding; const { parseMimeType } = window.__bootstrap.mimesniff; + const { DOMException } = window.__bootstrap.domException; const state = Symbol("[[state]]"); const result = Symbol("[[result]]"); diff --git a/extensions/web/12_location.js b/extensions/web/12_location.js index 75012396a9..dd56fb47b7 100644 --- a/extensions/web/12_location.js +++ b/extensions/web/12_location.js @@ -3,6 +3,8 @@ ((window) => { const { URL } = window.__bootstrap.url; + const { DOMException } = window.__bootstrap.domException; + const locationConstructorKey = Symbol("locationConstuctorKey"); // The differences between the definitions of `Location` and `WorkerLocation` diff --git a/extensions/web/13_message_port.js b/extensions/web/13_message_port.js index 1928409f20..ae8e148f42 100644 --- a/extensions/web/13_message_port.js +++ b/extensions/web/13_message_port.js @@ -13,6 +13,7 @@ const webidl = window.__bootstrap.webidl; const { setEventTargetData } = window.__bootstrap.eventTarget; const { defineEventHandler } = window.__bootstrap.event; + const { DOMException } = window.__bootstrap.domException; class MessageChannel { /** @type {MessagePort} */ diff --git a/extensions/web/internal.d.ts b/extensions/web/internal.d.ts index bbf529b770..bc3982a882 100644 --- a/extensions/web/internal.d.ts +++ b/extensions/web/internal.d.ts @@ -44,6 +44,10 @@ declare namespace globalThis { forgivingBase64Decode(data: string): Uint8Array; }; + declare var domException: { + DOMException: typeof DOMException; + }; + declare namespace mimesniff { declare interface MimeType { type: string; diff --git a/extensions/webgpu/01_webgpu.js b/extensions/webgpu/01_webgpu.js index 5ff6cde461..b28e7a0e42 100644 --- a/extensions/webgpu/01_webgpu.js +++ b/extensions/webgpu/01_webgpu.js @@ -12,6 +12,7 @@ const core = window.Deno.core; const webidl = window.__bootstrap.webidl; const eventTarget = window.__bootstrap.eventTarget; + const { DOMException } = window.__bootstrap.domException; /** * @param {any} self diff --git a/extensions/websocket/01_websocket.js b/extensions/websocket/01_websocket.js index fe1158d09b..38cba86624 100644 --- a/extensions/websocket/01_websocket.js +++ b/extensions/websocket/01_websocket.js @@ -6,6 +6,7 @@ const { URL } = window.__bootstrap.url; const webidl = window.__bootstrap.webidl; const { HTTP_TOKEN_CODE_POINT_RE } = window.__bootstrap.infra; + const { DOMException } = window.__bootstrap.domException; webidl.converters["sequence or DOMString"] = (V, opts) => { // Union for (sequence or DOMString) diff --git a/runtime/js/12_io.js b/runtime/js/12_io.js index 2380e0283f..a150153518 100644 --- a/runtime/js/12_io.js +++ b/runtime/js/12_io.js @@ -7,12 +7,14 @@ ((window) => { const core = window.Deno.core; + const { DOMException } = window.__bootstrap.domException; const { Uint8Array, ArrayPrototypePush, TypedArrayPrototypeSubarray, TypedArrayPrototypeSet, } = window.__bootstrap.primordials; + const DEFAULT_BUFFER_SIZE = 32 * 1024; // Seek whence values. // https://golang.org/pkg/io/#pkg-constants diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index 91d485069d..c3e4a392cf 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -41,6 +41,7 @@ delete Object.prototype.__proto__; const denoNsUnstable = window.__bootstrap.denoNsUnstable; const errors = window.__bootstrap.errors.errors; const webidl = window.__bootstrap.webidl; + const domException = window.__bootstrap.domException; const { defineEventHandler } = window.__bootstrap.webUtil; const { deserializeJsMessageData, serializeJsMessageData } = window.__bootstrap.messagePort; @@ -219,25 +220,25 @@ delete Object.prototype.__proto__; core.registerErrorBuilder( "DOMExceptionOperationError", function DOMExceptionOperationError(msg) { - return new DOMException(msg, "OperationError"); + return new domException.DOMException(msg, "OperationError"); }, ); core.registerErrorBuilder( "DOMExceptionQuotaExceededError", function DOMExceptionQuotaExceededError(msg) { - return new DOMException(msg, "QuotaExceededError"); + return new domException.DOMException(msg, "QuotaExceededError"); }, ); core.registerErrorBuilder( "DOMExceptionNotSupportedError", function DOMExceptionNotSupportedError(msg) { - return new DOMException(msg, "NotSupported"); + return new domException.DOMException(msg, "NotSupported"); }, ); core.registerErrorBuilder( "DOMExceptionInvalidCharacterError", function DOMExceptionInvalidCharacterError(msg) { - return new DOMException(msg, "InvalidCharacterError"); + return new domException.DOMException(msg, "InvalidCharacterError"); }, ); } @@ -299,7 +300,7 @@ delete Object.prototype.__proto__; streams.CountQueuingStrategy, ), CustomEvent: util.nonEnumerable(CustomEvent), - DOMException: util.nonEnumerable(DOMException), + DOMException: util.nonEnumerable(domException.DOMException), ErrorEvent: util.nonEnumerable(ErrorEvent), Event: util.nonEnumerable(Event), EventTarget: util.nonEnumerable(EventTarget), diff --git a/tools/cut_a_release.md b/tools/cut_a_release.md index 2d3fb8914e..ef3f29dc36 100644 --- a/tools/cut_a_release.md +++ b/tools/cut_a_release.md @@ -42,10 +42,12 @@ between the crates, it must be done in specific order: first - `bench_util` - crates in `extensions/` directory - - `deno_fetch`, `deno_crypto` and `deno_webstorage` depend on `deno_web`, so - the latter must be bumped and released first + - `deno_fetch`, `deno_crypto`, `deno_timers` and `deno_webstorage` depend on + `deno_web`, so the latter must be bumped and released first - `deno_url` depends on `deno_webidl`, so the latter must be bumped and released first + - `deno_timers` depends on `deno_url`, so the latter must be bumped and + released first - `runtime` - this crate depends on `deno_core` and all crates in `extensions/` directory