From a567f60a24598d0cf277f04a85ec7d9d062dae04 Mon Sep 17 00:00:00 2001 From: Kitson Kelly Date: Fri, 29 Apr 2022 13:47:58 +1000 Subject: [PATCH] fix(cli): add dom.extras lib (#14430) Closes: #12558 Fixes: #14344 --- cli/dts/lib.dom.d.ts | 2 +- cli/dts/lib.dom.extras.d.ts | 148 +++++++++++++++++++++++ cli/tests/integration/run_tests.rs | 5 + cli/tests/testdata/lib_dom_extras.ts | 17 +++ cli/tests/testdata/lib_dom_extras.ts.out | 2 + cli/tsc.rs | 1 + cli/tsc/00_typescript.js | 1 + tools/update_typescript.md | 8 +- 8 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 cli/dts/lib.dom.extras.d.ts create mode 100644 cli/tests/testdata/lib_dom_extras.ts create mode 100644 cli/tests/testdata/lib_dom_extras.ts.out diff --git a/cli/dts/lib.dom.d.ts b/cli/dts/lib.dom.d.ts index 04fa72459537a..c5eafbec80c9c 100644 --- a/cli/dts/lib.dom.d.ts +++ b/cli/dts/lib.dom.d.ts @@ -16,7 +16,7 @@ and limitations under the License. /// - +/// ///////////////////////////// /// Window APIs diff --git a/cli/dts/lib.dom.extras.d.ts b/cli/dts/lib.dom.extras.d.ts new file mode 100644 index 0000000000000..8d21ae5750f6a --- /dev/null +++ b/cli/dts/lib.dom.extras.d.ts @@ -0,0 +1,148 @@ +// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. + +/* + * This library contains DOM standards that are not currently included in the + * distributed `lib.dom.d.ts` file with TypeScript. + */ + +/// + +interface AbortSignal extends EventTarget { + readonly reason?: unknown; +} + +declare interface URLPatternInit { + protocol?: string; + username?: string; + password?: string; + hostname?: string; + port?: string; + pathname?: string; + search?: string; + hash?: string; + baseURL?: string; +} + +declare type URLPatternInput = string | URLPatternInit; + +declare interface URLPatternComponentResult { + input: string; + groups: Record; +} + +/** `URLPatternResult` is the object returned from `URLPattern.exec`. */ +declare interface URLPatternResult { + /** The inputs provided when matching. */ + inputs: [URLPatternInit] | [URLPatternInit, string]; + + /** The matched result for the `protocol` matcher. */ + protocol: URLPatternComponentResult; + /** The matched result for the `username` matcher. */ + username: URLPatternComponentResult; + /** The matched result for the `password` matcher. */ + password: URLPatternComponentResult; + /** The matched result for the `hostname` matcher. */ + hostname: URLPatternComponentResult; + /** The matched result for the `port` matcher. */ + port: URLPatternComponentResult; + /** The matched result for the `pathname` matcher. */ + pathname: URLPatternComponentResult; + /** The matched result for the `search` matcher. */ + search: URLPatternComponentResult; + /** The matched result for the `hash` matcher. */ + hash: URLPatternComponentResult; +} + +/** + * The URLPattern API provides a web platform primitive for matching URLs based + * on a convenient pattern syntax. + * + * The syntax is based on path-to-regexp. Wildcards, named capture groups, + * regular groups, and group modifiers are all supported. + * + * ```ts + * // Specify the pattern as structured data. + * const pattern = new URLPattern({ pathname: "/users/:user" }); + * const match = pattern.exec("/users/joe"); + * console.log(match.pathname.groups.user); // joe + * ``` + * + * ```ts + * // Specify a fully qualified string pattern. + * const pattern = new URLPattern("https://example.com/books/:id"); + * console.log(pattern.test("https://example.com/books/123")); // true + * console.log(pattern.test("https://deno.land/books/123")); // false + * ``` + * + * ```ts + * // Specify a relative string pattern with a base URL. + * const pattern = new URLPattern("/:article", "https://blog.example.com"); + * console.log(pattern.test("https://blog.example.com/article")); // true + * console.log(pattern.test("https://blog.example.com/article/123")); // false + * ``` + */ +declare class URLPattern { + constructor(input: URLPatternInput, baseURL?: string); + + /** + * Test if the given input matches the stored pattern. + * + * The input can either be provided as a url string (with an optional base), + * or as individual components in the form of an object. + * + * ```ts + * const pattern = new URLPattern("https://example.com/books/:id"); + * + * // Test a url string. + * console.log(pattern.test("https://example.com/books/123")); // true + * + * // Test a relative url with a base. + * console.log(pattern.test("/books/123", "https://example.com")); // true + * + * // Test an object of url components. + * console.log(pattern.test({ pathname: "/books/123" })); // true + * ``` + */ + test(input: URLPatternInput, baseURL?: string): boolean; + + /** + * Match the given input against the stored pattern. + * + * The input can either be provided as a url string (with an optional base), + * or as individual components in the form of an object. + * + * ```ts + * const pattern = new URLPattern("https://example.com/books/:id"); + * + * // Match a url string. + * let match = pattern.exec("https://example.com/books/123"); + * console.log(match.pathname.groups.id); // 123 + * + * // Match a relative url with a base. + * match = pattern.exec("/books/123", "https://example.com"); + * console.log(match.pathname.groups.id); // 123 + * + * // Match an object of url components. + * match = pattern.exec({ pathname: "/books/123" }); + * console.log(match.pathname.groups.id); // 123 + * ``` + */ + exec(input: URLPatternInput, baseURL?: string): URLPatternResult | null; + + /** The pattern string for the `protocol`. */ + readonly protocol: string; + /** The pattern string for the `username`. */ + readonly username: string; + /** The pattern string for the `password`. */ + readonly password: string; + /** The pattern string for the `hostname`. */ + readonly hostname: string; + /** The pattern string for the `port`. */ + readonly port: string; + /** The pattern string for the `pathname`. */ + readonly pathname: string; + /** The pattern string for the `search`. */ + readonly search: string; + /** The pattern string for the `hash`. */ + readonly hash: string; +} diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs index 4c4b42142f7e2..09c09d103c0bc 100644 --- a/cli/tests/integration/run_tests.rs +++ b/cli/tests/integration/run_tests.rs @@ -991,6 +991,11 @@ itest!(lib_dom_asynciterable { output: "lib_dom_asynciterable.ts.out", }); +itest!(lib_dom_extras { + args: "run --quiet --unstable --reload lib_dom_extras.ts", + output: "lib_dom_extras.ts.out", +}); + itest!(lib_ref { args: "run --quiet --unstable --reload lib_ref.ts", output: "lib_ref.ts.out", diff --git a/cli/tests/testdata/lib_dom_extras.ts b/cli/tests/testdata/lib_dom_extras.ts new file mode 100644 index 0000000000000..c061bd36208ea --- /dev/null +++ b/cli/tests/testdata/lib_dom_extras.ts @@ -0,0 +1,17 @@ +const { diagnostics, files } = await Deno.emit("/main.ts", { + compilerOptions: { + target: "esnext", + lib: ["esnext", "dom"], + }, + sources: { + "/main.ts": `const as = new AbortSignal(); + console.log(as.reason); + + const up = new URLPattern("https://example.com/books/:id"); + console.log(up); + `, + }, +}); + +console.log(diagnostics); +console.log(Object.keys(files).sort()); diff --git a/cli/tests/testdata/lib_dom_extras.ts.out b/cli/tests/testdata/lib_dom_extras.ts.out new file mode 100644 index 0000000000000..8b5e7adb6d11a --- /dev/null +++ b/cli/tests/testdata/lib_dom_extras.ts.out @@ -0,0 +1,2 @@ +[] +[ "[WILDCARD]/main.ts.js", "[WILDCARD]/main.ts.js.map" ] diff --git a/cli/tsc.rs b/cli/tsc.rs index 67285ef7d01a1..499360722186f 100644 --- a/cli/tsc.rs +++ b/cli/tsc.rs @@ -88,6 +88,7 @@ pub static STATIC_ASSETS: Lazy> = inc!("lib.dom.asynciterable.d.ts"), ), ("lib.dom.d.ts", inc!("lib.dom.d.ts")), + ("lib.dom.extras.d.ts", inc!("lib.dom.extras.d.ts")), ("lib.dom.iterable.d.ts", inc!("lib.dom.iterable.d.ts")), ("lib.es6.d.ts", inc!("lib.es6.d.ts")), ("lib.es2016.full.d.ts", inc!("lib.es2016.full.d.ts")), diff --git a/cli/tsc/00_typescript.js b/cli/tsc/00_typescript.js index e239cb79e0df8..360278539058e 100644 --- a/cli/tsc/00_typescript.js +++ b/cli/tsc/00_typescript.js @@ -38443,6 +38443,7 @@ var ts; ["dom", "lib.dom.d.ts"], ["dom.iterable", "lib.dom.iterable.d.ts"], ["dom.asynciterable", "lib.dom.asynciterable.d.ts"], + ["dom.extras", "lib.dom.extras.d.ts"], ["webworker", "lib.webworker.d.ts"], ["webworker.importscripts", "lib.webworker.importscripts.d.ts"], ["webworker.iterable", "lib.webworker.iterable.d.ts"], diff --git a/tools/update_typescript.md b/tools/update_typescript.md index 0b4d54b3349d8..e012c7f77e2c5 100644 --- a/tools/update_typescript.md +++ b/tools/update_typescript.md @@ -84,6 +84,12 @@ contextual awareness, it is the author's opinion that it is best to spend the - We add `lib.dom.asynciterables.d.ts` because for some reason TypeScript has not built these into the libraries. (See: https://github.com/microsoft/TypeScript/issues/29867) + - We add `lib.dom.extras.d.ts` because TypeScript is often behind + supporting some DOM standards that Deno supports and when people use + `lib: ["dom", "deno.ns"]` they will get error messages that are confusing + when using libraries that take advantage of these standards. We add the + library to `lib.dom.d.ts`, so it is automatically included when using the + `dom` lib under Deno. 7. Based on the changes to the lib files, you will need to edit the map of lib names to files in the TypeScript compiler (`deno/cli/tsc/00_typescript.js`). @@ -104,7 +110,7 @@ contextual awareness, it is the author's opinion that it is best to spend the maps `esnext.*` values to the ratified version of them to ensure they are less "breaking" so you will want to make sure, like for `esnext.array` that it points at `lib.esnext.array.d.ts`. You will also want to revert the - deletion of `dom.asynciterables`. + deletion of `dom.asynciterables` and `dom.extras`. 8. For any new lib files that were added, but not included in the snapshot (e.g. `lib.es####.full.d.ts`) add them to `STATIC_ASSETS` in `deno/cli/tsc.rs`.