From f26cf910da0767427e229bba641b5b81c140ada5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Mon, 4 Jul 2022 23:05:09 +0200 Subject: [PATCH 01/16] feat: import.meta.resolve() --- core/bindings.rs | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ meta.mjs | 4 ++++ 2 files changed, 53 insertions(+) create mode 100644 meta.mjs diff --git a/core/bindings.rs b/core/bindings.rs index 47632d00dd3b5d..17232022a61868 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -271,6 +271,55 @@ pub extern "C" fn host_initialize_import_meta_object_callback( let main_key = v8::String::new(scope, "main").unwrap(); let main_val = v8::Boolean::new(scope, info.main); meta.create_data_property(scope, main_key.into(), main_val.into()); + + let resolve_key = v8::String::new(scope, "resolve").unwrap(); + let val = v8::Function::new(scope, import_meta_resolve).unwrap(); + val.set_name(resolve_key); + meta.set(scope, resolve_key.into(), val.into()); +} + +fn import_meta_resolve( + scope: &mut v8::HandleScope, + args: v8::FunctionCallbackArguments, + mut rv: v8::ReturnValue, +) { + if args.length() < 1 + || !args.get(0).is_string() + || (args.length() == 2 && !args.get(1).is_string()) + { + return throw_type_error(scope, "Invalid arguments"); + } + + let referrer = if args.length() == 2 { + let str = v8::Local::::try_from(args.get(1)).unwrap(); + str.to_rust_string_lossy(scope) + } else { + let receiver = args.this(); + let url_key = v8::String::new(scope, "url").unwrap(); + let url_prop = receiver.get(scope, url_key.into()).unwrap(); + url_prop.to_rust_string_lossy(scope) + }; + let specifier = v8::Local::::try_from(args.get(0)).unwrap(); + let module_map_rc = JsRuntime::module_map(scope); + let loader = { + let module_map = module_map_rc.borrow(); + module_map.loader.clone() + }; + let resolver = v8::PromiseResolver::new(scope).unwrap(); + let promise = resolver.get_promise(scope); + rv.set(promise.into()); + + match loader.resolve(&specifier.to_rust_string_lossy(scope), &referrer, false) + { + Ok(resolved) => { + let resolved_val = serde_v8::to_v8(scope, resolved.as_str()).unwrap(); + resolver.resolve(scope, resolved_val); + } + Err(err) => { + let rejected_val = serde_v8::to_v8(scope, err.to_string()).unwrap(); + resolver.reject(scope, rejected_val); + } + }; } pub extern "C" fn promise_reject_callback(message: v8::PromiseRejectMessage) { diff --git a/meta.mjs b/meta.mjs new file mode 100644 index 00000000000000..14481344e7fd77 --- /dev/null +++ b/meta.mjs @@ -0,0 +1,4 @@ +console.log("I am", import.meta.url, import.meta); +console.log("Resolving ./foo.js", await import.meta.resolve("./foo.js")); +console.log("Resolving ./foo.js from ./bar.js", await import.meta.resolve("./foo.js", "./bar.js")); + From a22db346a4758667bd238f703058568cf12619c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Mon, 4 Jul 2022 23:10:03 +0200 Subject: [PATCH 02/16] reset CI From 1850382c2223778b6428cebda7273837e02530b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Mon, 4 Jul 2022 23:40:23 +0200 Subject: [PATCH 03/16] update TS definitions, add test --- cli/dts/lib.deno.ns.d.ts | 15 +++++++++++++ cli/tests/testdata/import_meta.ts | 6 ++++++ cli/tests/testdata/import_meta.ts.out | 2 ++ core/bindings.rs | 31 ++++++++++++++------------- meta.mjs | 4 ---- 5 files changed, 39 insertions(+), 19 deletions(-) delete mode 100644 meta.mjs diff --git a/cli/dts/lib.deno.ns.d.ts b/cli/dts/lib.deno.ns.d.ts index b13acc238a7715..5d5349bada81b1 100644 --- a/cli/dts/lib.deno.ns.d.ts +++ b/cli/dts/lib.deno.ns.d.ts @@ -21,6 +21,21 @@ declare interface ImportMeta { * ``` */ main: boolean; + + /** A function that returns resolved specifier as if it would be imported + * using `import(specifier)` from a module located at `baseUrl`. + * + * Specifier is resolved relative to optional `baseUrl`, which defaults to + * the URL of the active script. + * + * ```ts + * console.log(import.meta.resolve("./foo.js")); + * // file:///dev/foo.js + * console.log(import.meta.resolve("./foo.js", "../bar.js")); + * // file:///foo.js + * ``` + */ + resolve(specifier: string, baseUrl?: string): string; } /** Deno supports user timing Level 3 (see: https://w3c.github.io/user-timing) diff --git a/cli/tests/testdata/import_meta.ts b/cli/tests/testdata/import_meta.ts index d111059ea1348a..05cfd6878caf37 100644 --- a/cli/tests/testdata/import_meta.ts +++ b/cli/tests/testdata/import_meta.ts @@ -1,3 +1,9 @@ console.log("import_meta", import.meta.url, import.meta.main); import "./import_meta2.ts"; + +console.log("Resolving ./foo.js", import.meta.resolve("./foo.js")); +console.log( + "Resolving ./foo.js from ./bar.js", + import.meta.resolve("./foo.js", "./bar.js"), +); diff --git a/cli/tests/testdata/import_meta.ts.out b/cli/tests/testdata/import_meta.ts.out index f38aa98ea1924e..36bbb82bd541cf 100644 --- a/cli/tests/testdata/import_meta.ts.out +++ b/cli/tests/testdata/import_meta.ts.out @@ -1,2 +1,4 @@ import_meta2 [WILDCARD]import_meta2.ts false import_meta [WILDCARD]import_meta.ts true +Resolving ./foo.js file:///[WILDCARD]/foo.js +Resolving ./foo.js from ./bar.js file:///[WILDCARD]foo.js \ No newline at end of file diff --git a/core/bindings.rs b/core/bindings.rs index 17232022a61868..40bd67efcc3eb7 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -290,34 +290,35 @@ fn import_meta_resolve( return throw_type_error(scope, "Invalid arguments"); } + let tc_scope = &mut v8::TryCatch::new(scope); let referrer = if args.length() == 2 { let str = v8::Local::::try_from(args.get(1)).unwrap(); - str.to_rust_string_lossy(scope) + str.to_rust_string_lossy(tc_scope) } else { let receiver = args.this(); - let url_key = v8::String::new(scope, "url").unwrap(); - let url_prop = receiver.get(scope, url_key.into()).unwrap(); - url_prop.to_rust_string_lossy(scope) + let url_key = v8::String::new(tc_scope, "url").unwrap(); + let url_prop = receiver.get(tc_scope, url_key.into()).unwrap(); + url_prop.to_rust_string_lossy(tc_scope) }; let specifier = v8::Local::::try_from(args.get(0)).unwrap(); - let module_map_rc = JsRuntime::module_map(scope); + let module_map_rc = JsRuntime::module_map(tc_scope); let loader = { let module_map = module_map_rc.borrow(); module_map.loader.clone() }; - let resolver = v8::PromiseResolver::new(scope).unwrap(); - let promise = resolver.get_promise(scope); - rv.set(promise.into()); - - match loader.resolve(&specifier.to_rust_string_lossy(scope), &referrer, false) - { + match loader.resolve( + &specifier.to_rust_string_lossy(tc_scope), + &referrer, + false, + ) { Ok(resolved) => { - let resolved_val = serde_v8::to_v8(scope, resolved.as_str()).unwrap(); - resolver.resolve(scope, resolved_val); + let resolved_val = serde_v8::to_v8(tc_scope, resolved.as_str()).unwrap(); + rv.set(resolved_val.into()); } Err(err) => { - let rejected_val = serde_v8::to_v8(scope, err.to_string()).unwrap(); - resolver.reject(scope, rejected_val); + let message = v8::String::new(tc_scope, &err.to_string()).unwrap(); + let exception = v8::Exception::error(tc_scope, message); + tc_scope.throw_exception(exception); } }; } diff --git a/meta.mjs b/meta.mjs deleted file mode 100644 index 14481344e7fd77..00000000000000 --- a/meta.mjs +++ /dev/null @@ -1,4 +0,0 @@ -console.log("I am", import.meta.url, import.meta); -console.log("Resolving ./foo.js", await import.meta.resolve("./foo.js")); -console.log("Resolving ./foo.js from ./bar.js", await import.meta.resolve("./foo.js", "./bar.js")); - From eca534f479dfcca41089cd5e3117773c94267419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Mon, 4 Jul 2022 23:42:09 +0200 Subject: [PATCH 04/16] lint & fix test --- cli/tests/testdata/import_meta.ts.out | 2 +- core/bindings.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/tests/testdata/import_meta.ts.out b/cli/tests/testdata/import_meta.ts.out index 36bbb82bd541cf..9fffd0a9e70432 100644 --- a/cli/tests/testdata/import_meta.ts.out +++ b/cli/tests/testdata/import_meta.ts.out @@ -1,4 +1,4 @@ import_meta2 [WILDCARD]import_meta2.ts false import_meta [WILDCARD]import_meta.ts true Resolving ./foo.js file:///[WILDCARD]/foo.js -Resolving ./foo.js from ./bar.js file:///[WILDCARD]foo.js \ No newline at end of file +Resolving ./foo.js from ./bar.js file:///[WILDCARD]foo.js diff --git a/core/bindings.rs b/core/bindings.rs index e10b7dc9d6c545..af8dc19a32c38d 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -313,7 +313,7 @@ fn import_meta_resolve( ) { Ok(resolved) => { let resolved_val = serde_v8::to_v8(tc_scope, resolved.as_str()).unwrap(); - rv.set(resolved_val.into()); + rv.set(resolved_val); } Err(err) => { let message = v8::String::new(tc_scope, &err.to_string()).unwrap(); From 01addd0980e6b392393b6b81f7baba531786c19d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Tue, 5 Jul 2022 21:30:16 +0200 Subject: [PATCH 05/16] add tests for import maps --- cli/tests/integration/run_tests.rs | 2 +- cli/tests/testdata/import_meta.importmap.json | 11 ++++++++ cli/tests/testdata/import_meta.ts | 25 +++++++++++++++++++ cli/tests/testdata/import_meta.ts.out | 7 ++++++ core/bindings.rs | 11 ++++---- 5 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 cli/tests/testdata/import_meta.importmap.json diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs index 1cd1db0ef6b801..d8068db0af9977 100644 --- a/cli/tests/integration/run_tests.rs +++ b/cli/tests/integration/run_tests.rs @@ -944,7 +944,7 @@ itest!(if_main { }); itest!(import_meta { - args: "run --quiet --reload import_meta.ts", + args: "run --quiet --reload --import-map=import_meta.importmap.json import_meta.ts", output: "import_meta.ts.out", }); diff --git a/cli/tests/testdata/import_meta.importmap.json b/cli/tests/testdata/import_meta.importmap.json new file mode 100644 index 00000000000000..f8c056afd69fd9 --- /dev/null +++ b/cli/tests/testdata/import_meta.importmap.json @@ -0,0 +1,11 @@ +{ + "imports": { + "bare": "https://example.com/", + "https://example.com/rewrite": "https://example.com/rewritten", + + "1": "https://example.com/PASS-1", + "null": "https://example.com/PASS-null", + "undefined": "https://example.com/PASS-undefined", + "[object Object]": "https://example.com/PASS-object" + } +} diff --git a/cli/tests/testdata/import_meta.ts b/cli/tests/testdata/import_meta.ts index 05cfd6878caf37..ef117cf2852be1 100644 --- a/cli/tests/testdata/import_meta.ts +++ b/cli/tests/testdata/import_meta.ts @@ -7,3 +7,28 @@ console.log( "Resolving ./foo.js from ./bar.js", import.meta.resolve("./foo.js", "./bar.js"), ); +console.log("Resolving bare from import map", import.meta.resolve("bare")); +console.log( + "Resolving https://example.com/rewrite from import map", + import.meta.resolve("https://example.com/rewrite"), +); +console.log( + "Resolving https://example.com/rewrite from import map", + import.meta.resolve("https://example.com/rewrite"), +); +console.log( + "Resolving without a value from import map", + import.meta.resolve(), +); +console.log( + "Resolving undefined from import map", + import.meta.resolve("https://example.com/PASS-undefined"), +); +console.log( + "Resolving 1 from import map", + import.meta.resolve("https://example.com/PASS-1"), +); +console.log( + "Resolving null from import map", + import.meta.resolve("https://example.com/PASS-null"), +); diff --git a/cli/tests/testdata/import_meta.ts.out b/cli/tests/testdata/import_meta.ts.out index 9fffd0a9e70432..8c74943907b90b 100644 --- a/cli/tests/testdata/import_meta.ts.out +++ b/cli/tests/testdata/import_meta.ts.out @@ -2,3 +2,10 @@ import_meta2 [WILDCARD]import_meta2.ts false import_meta [WILDCARD]import_meta.ts true Resolving ./foo.js file:///[WILDCARD]/foo.js Resolving ./foo.js from ./bar.js file:///[WILDCARD]foo.js +Resolving bare from import map https://example.com/ +Resolving https://example.com/rewrite from import map https://example.com/rewritten +Resolving https://example.com/rewrite from import map https://example.com/rewritten +Resolving without a value from import map https://example.com/PASS-undefined +Resolving undefined from import map https://example.com/PASS-undefined +Resolving 1 from import map https://example.com/PASS-1 +Resolving null from import map https://example.com/PASS-null diff --git a/core/bindings.rs b/core/bindings.rs index af8dc19a32c38d..1a6d482b74549f 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -283,14 +283,16 @@ fn import_meta_resolve( args: v8::FunctionCallbackArguments, mut rv: v8::ReturnValue, ) { - if args.length() < 1 - || !args.get(0).is_string() - || (args.length() == 2 && !args.get(1).is_string()) - { + if args.length() == 2 && !args.get(1).is_string() { return throw_type_error(scope, "Invalid arguments"); } let tc_scope = &mut v8::TryCatch::new(scope); + let maybe_arg_str = args.get(0).to_string(tc_scope); + if maybe_arg_str.is_none() { + return throw_type_error(tc_scope, "Invalid arguments"); + } + let specifier = maybe_arg_str.unwrap(); let referrer = if args.length() == 2 { let str = v8::Local::::try_from(args.get(1)).unwrap(); str.to_rust_string_lossy(tc_scope) @@ -300,7 +302,6 @@ fn import_meta_resolve( let url_prop = receiver.get(tc_scope, url_key.into()).unwrap(); url_prop.to_rust_string_lossy(tc_scope) }; - let specifier = v8::Local::::try_from(args.get(0)).unwrap(); let module_map_rc = JsRuntime::module_map(tc_scope); let loader = { let module_map = module_map_rc.borrow(); From c9b4e4b3440d6db2a39cb432701a2441f70f8865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Mon, 11 Jul 2022 17:35:29 +0200 Subject: [PATCH 06/16] revert 2nd argument --- cli/dts/lib.deno.ns.d.ts | 9 ++------- cli/tests/testdata/import_meta.ts | 4 ---- cli/tests/testdata/import_meta.ts.out | 1 - core/bindings.rs | 7 ++----- 4 files changed, 4 insertions(+), 17 deletions(-) diff --git a/cli/dts/lib.deno.ns.d.ts b/cli/dts/lib.deno.ns.d.ts index 5d5349bada81b1..e5499c93e9ebad 100644 --- a/cli/dts/lib.deno.ns.d.ts +++ b/cli/dts/lib.deno.ns.d.ts @@ -23,19 +23,14 @@ declare interface ImportMeta { main: boolean; /** A function that returns resolved specifier as if it would be imported - * using `import(specifier)` from a module located at `baseUrl`. - * - * Specifier is resolved relative to optional `baseUrl`, which defaults to - * the URL of the active script. + * using `import(specifier)`. * * ```ts * console.log(import.meta.resolve("./foo.js")); * // file:///dev/foo.js - * console.log(import.meta.resolve("./foo.js", "../bar.js")); - * // file:///foo.js * ``` */ - resolve(specifier: string, baseUrl?: string): string; + resolve(specifier: string): string; } /** Deno supports user timing Level 3 (see: https://w3c.github.io/user-timing) diff --git a/cli/tests/testdata/import_meta.ts b/cli/tests/testdata/import_meta.ts index ef117cf2852be1..d7af3eca46a684 100644 --- a/cli/tests/testdata/import_meta.ts +++ b/cli/tests/testdata/import_meta.ts @@ -3,10 +3,6 @@ console.log("import_meta", import.meta.url, import.meta.main); import "./import_meta2.ts"; console.log("Resolving ./foo.js", import.meta.resolve("./foo.js")); -console.log( - "Resolving ./foo.js from ./bar.js", - import.meta.resolve("./foo.js", "./bar.js"), -); console.log("Resolving bare from import map", import.meta.resolve("bare")); console.log( "Resolving https://example.com/rewrite from import map", diff --git a/cli/tests/testdata/import_meta.ts.out b/cli/tests/testdata/import_meta.ts.out index 8c74943907b90b..c8c43da79995e2 100644 --- a/cli/tests/testdata/import_meta.ts.out +++ b/cli/tests/testdata/import_meta.ts.out @@ -1,7 +1,6 @@ import_meta2 [WILDCARD]import_meta2.ts false import_meta [WILDCARD]import_meta.ts true Resolving ./foo.js file:///[WILDCARD]/foo.js -Resolving ./foo.js from ./bar.js file:///[WILDCARD]foo.js Resolving bare from import map https://example.com/ Resolving https://example.com/rewrite from import map https://example.com/rewritten Resolving https://example.com/rewrite from import map https://example.com/rewritten diff --git a/core/bindings.rs b/core/bindings.rs index 1a6d482b74549f..eedc84107d26e3 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -283,7 +283,7 @@ fn import_meta_resolve( args: v8::FunctionCallbackArguments, mut rv: v8::ReturnValue, ) { - if args.length() == 2 && !args.get(1).is_string() { + if args.length() > 1 { return throw_type_error(scope, "Invalid arguments"); } @@ -293,10 +293,7 @@ fn import_meta_resolve( return throw_type_error(tc_scope, "Invalid arguments"); } let specifier = maybe_arg_str.unwrap(); - let referrer = if args.length() == 2 { - let str = v8::Local::::try_from(args.get(1)).unwrap(); - str.to_rust_string_lossy(tc_scope) - } else { + let referrer = { let receiver = args.this(); let url_key = v8::String::new(tc_scope, "url").unwrap(); let url_prop = receiver.get(tc_scope, url_key.into()).unwrap(); From 20a2bda16b1569e42ac52d00a5197cf5d92f3b08 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Wed, 13 Jul 2022 17:27:27 -0400 Subject: [PATCH 07/16] feat(fmt): do not add a newline between a template and its tag (#15195) --- .dprint.json | 2 +- Cargo.lock | 4 ++-- cli/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.dprint.json b/.dprint.json index 50a40555e60643..fe4573cf29ecdf 100644 --- a/.dprint.json +++ b/.dprint.json @@ -46,7 +46,7 @@ "tools/wpt/manifest.json" ], "plugins": [ - "https://plugins.dprint.dev/typescript-0.69.5.wasm", + "https://plugins.dprint.dev/typescript-0.70.0.wasm", "https://plugins.dprint.dev/json-0.15.3.wasm", "https://plugins.dprint.dev/markdown-0.13.3.wasm", "https://plugins.dprint.dev/toml-0.5.4.wasm", diff --git a/Cargo.lock b/Cargo.lock index d925a0b4c28da7..52740f27452872 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1388,9 +1388,9 @@ dependencies = [ [[package]] name = "dprint-plugin-typescript" -version = "0.69.6" +version = "0.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b71449427ac9087807c1060b418b9127e734ebdd2a254822e8ca4fe8c5d3829" +checksum = "8615057f4eb72345350d10b6289cb320ff844255a1c2877e0a3692d2bb93f436" dependencies = [ "anyhow", "deno_ast", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 303e1f9aaa4b74..41feb09e4c49ac 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -65,7 +65,7 @@ data-url = "=0.1.1" dissimilar = "=1.0.3" dprint-plugin-json = "=0.15.3" dprint-plugin-markdown = "=0.13.3" -dprint-plugin-typescript = "=0.69.6" +dprint-plugin-typescript = "=0.70.0" encoding_rs = "=0.8.31" env_logger = "=0.9.0" eszip = "=0.22.0" From 4dcad0c87ad7b037045655e542864ace9dcf358d Mon Sep 17 00:00:00 2001 From: Kitson Kelly Date: Thu, 14 Jul 2022 11:12:18 +1000 Subject: [PATCH 08/16] feat(lsp): provide import map remapping diags and fixes (#15165) --- Cargo.lock | 17 ++- cli/Cargo.toml | 2 +- cli/lsp/diagnostics.rs | 273 +++++++++++++++++++++++++++++++++---- cli/lsp/language_server.rs | 2 + 4 files changed, 263 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52740f27452872..f6c756680ecf3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -812,7 +812,7 @@ dependencies = [ "fwdansi", "google-storage1", "http", - "import_map", + "import_map 0.12.1", "indexmap", "jsonc-parser", "libc", @@ -977,7 +977,7 @@ dependencies = [ "deno_ast", "deno_graph", "futures", - "import_map", + "import_map 0.11.0", "lazy_static", "regex", "serde", @@ -2186,6 +2186,19 @@ dependencies = [ "url 2.2.2", ] +[[package]] +name = "import_map" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b827962ca5aa6d5bbe313c14e73d7cc517487fa3bad380bb6bdbd8421e591a29" +dependencies = [ + "indexmap", + "log 0.4.17", + "serde", + "serde_json", + "url 2.2.2", +] + [[package]] name = "indexmap" version = "1.9.1" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 41feb09e4c49ac..12edb9413f5537 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -71,7 +71,7 @@ env_logger = "=0.9.0" eszip = "=0.22.0" fancy-regex = "=0.9.0" http = "=0.2.6" -import_map = "=0.11.0" +import_map = "=0.12.1" indexmap = "1.8.1" jsonc-parser = { version = "=0.19.0", features = ["serde"] } libc = "=0.2.126" diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs index 52ba1ba96938cd..7c5ab936a61b6c 100644 --- a/cli/lsp/diagnostics.rs +++ b/cli/lsp/diagnostics.rs @@ -6,7 +6,6 @@ use super::client::Client; use super::config::ConfigSnapshot; use super::documents; use super::documents::Document; -use super::documents::Documents; use super::language_server; use super::language_server::StateSnapshot; use super::performance::Performance; @@ -270,7 +269,7 @@ impl DiagnosticsServer { } let mark = performance.mark("update_diagnostics_deps", None::<()>); - let diagnostics = generate_deps_diagnostics( + let diagnostics = generate_deno_diagnostics( &snapshot, &config, token.clone(), @@ -572,11 +571,21 @@ struct DiagnosticDataRedirect { pub redirect: ModuleSpecifier, } +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +struct DiagnosticDataImportMapRemap { + pub from: String, + pub to: String, +} + /// An enum which represents diagnostic errors which originate from Deno itself. pub enum DenoDiagnostic { /// A `x-deno-warning` is associated with the specifier and should be displayed /// as a warning to the user. DenoWarn(String), + /// An informational diagnostic that indicates an existing specifier can be + /// remapped to an import map import specifier. + ImportMapRemap { from: String, to: String }, /// The import assertion type is incorrect. InvalidAssertType(String), /// A module requires an assertion type to be a valid import. @@ -606,6 +615,7 @@ impl DenoDiagnostic { match self { Self::DenoWarn(_) => "deno-warn", + Self::ImportMapRemap { .. } => "import-map-remap", Self::InvalidAssertType(_) => "invalid-assert-type", Self::NoAssertType => "no-assert-type", Self::NoCache(_) => "no-cache", @@ -633,6 +643,33 @@ impl DenoDiagnostic { ) -> Result { if let Some(lsp::NumberOrString::String(code)) = &diagnostic.code { let code_action = match code.as_str() { + "import-map-remap" => { + let data = diagnostic + .data + .clone() + .ok_or_else(|| anyhow!("Diagnostic is missing data"))?; + let DiagnosticDataImportMapRemap { from, to } = + serde_json::from_value(data)?; + lsp::CodeAction { + title: format!( + "Update \"{}\" to \"{}\" to use import map.", + from, to + ), + kind: Some(lsp::CodeActionKind::QUICKFIX), + diagnostics: Some(vec![diagnostic.clone()]), + edit: Some(lsp::WorkspaceEdit { + changes: Some(HashMap::from([( + specifier.clone(), + vec![lsp::TextEdit { + new_text: format!("\"{}\"", to), + range: diagnostic.range, + }], + )])), + ..Default::default() + }), + ..Default::default() + } + } "no-assert-type" => lsp::CodeAction { title: "Insert import assertion.".to_string(), kind: Some(lsp::CodeActionKind::QUICKFIX), @@ -717,7 +754,11 @@ impl DenoDiagnostic { if let Some(lsp::NumberOrString::String(code)) = code { matches!( code.as_str(), - "no-cache" | "no-cache-data" | "no-assert-type" | "redirect" + "import-map-remap" + | "no-cache" + | "no-cache-data" + | "no-assert-type" + | "redirect" ) } else { false @@ -729,6 +770,7 @@ impl DenoDiagnostic { pub fn to_lsp_diagnostic(&self, range: &lsp::Range) -> lsp::Diagnostic { let (severity, message, data) = match self { Self::DenoWarn(message) => (lsp::DiagnosticSeverity::WARNING, message.to_string(), None), + Self::ImportMapRemap { from, to } => (lsp::DiagnosticSeverity::HINT, format!("The import specifier can be remapped to \"{}\" which will resolve it via the active import map.", to), Some(json!({ "from": from, "to": to }))), Self::InvalidAssertType(assert_type) => (lsp::DiagnosticSeverity::ERROR, format!("The module is a JSON module and expected an assertion type of \"json\". Instead got \"{}\".", assert_type), None), Self::NoAssertType => (lsp::DiagnosticSeverity::ERROR, "The module is a JSON module and not being imported with an import assertion. Consider adding `assert { type: \"json\" }` to the import statement.".to_string(), None), Self::NoCache(specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Uncached or missing remote URL: \"{}\".", specifier), Some(json!({ "specifier": specifier }))), @@ -750,10 +792,9 @@ impl DenoDiagnostic { } } -fn diagnose_dependency( +fn diagnose_resolved( diagnostics: &mut Vec, - documents: &Documents, - cache_metadata: &cache::CacheMetadata, + snapshot: &language_server::StateSnapshot, resolved: &deno_graph::Resolved, is_dynamic: bool, maybe_assert_type: Option<&str>, @@ -765,7 +806,7 @@ fn diagnose_dependency( let range = documents::to_lsp_range(range); // If the module is a remote module and has a `X-Deno-Warning` header, we // want a warning diagnostic with that message. - if let Some(metadata) = cache_metadata.get(specifier) { + if let Some(metadata) = snapshot.cache_metadata.get(specifier) { if let Some(message) = metadata.get(&cache::MetadataKey::Warning).cloned() { @@ -773,7 +814,7 @@ fn diagnose_dependency( .push(DenoDiagnostic::DenoWarn(message).to_lsp_diagnostic(&range)); } } - if let Some(doc) = documents.get(specifier) { + if let Some(doc) = snapshot.documents.get(specifier) { let doc_specifier = doc.specifier(); // If the module was redirected, we want to issue an informational // diagnostic that indicates this. This then allows us to issue a code @@ -828,9 +869,54 @@ fn diagnose_dependency( } } -/// Generate diagnostics for dependencies of a module, attempting to resolve -/// dependencies on the local file system or in the DENO_DIR cache. -async fn generate_deps_diagnostics( +/// Generate diagnostics related to a dependency. The dependency is analyzed to +/// determine if it can be remapped to the active import map as well as surface +/// any diagnostics related to the resolved code or type dependency. +fn diagnose_dependency( + diagnostics: &mut Vec, + snapshot: &language_server::StateSnapshot, + referrer: &ModuleSpecifier, + dependency_key: &str, + dependency: &deno_graph::Dependency, +) { + if let Some(import_map) = &snapshot.maybe_import_map { + if let Resolved::Ok { + specifier, range, .. + } = &dependency.maybe_code + { + if let Some(to) = import_map.lookup(specifier, referrer) { + if dependency_key != to { + diagnostics.push( + DenoDiagnostic::ImportMapRemap { + from: dependency_key.to_string(), + to, + } + .to_lsp_diagnostic(&documents::to_lsp_range(range)), + ); + } + } + } + } + diagnose_resolved( + diagnostics, + snapshot, + &dependency.maybe_code, + dependency.is_dynamic, + dependency.maybe_assert_type.as_deref(), + ); + diagnose_resolved( + diagnostics, + snapshot, + &dependency.maybe_type, + dependency.is_dynamic, + dependency.maybe_assert_type.as_deref(), + ); +} + +/// Generate diagnostics that come from Deno module resolution logic (like +/// dependencies) or other Deno specific diagnostics, like the ability to use +/// an import map to shorten an URL. +async fn generate_deno_diagnostics( snapshot: &language_server::StateSnapshot, config: &ConfigSnapshot, token: CancellationToken, @@ -844,22 +930,13 @@ async fn generate_deps_diagnostics( let mut diagnostics = Vec::new(); let specifier = document.specifier(); if config.specifier_enabled(specifier) { - for (_, dependency) in document.dependencies() { - diagnose_dependency( - &mut diagnostics, - &snapshot.documents, - &snapshot.cache_metadata, - &dependency.maybe_code, - dependency.is_dynamic, - dependency.maybe_assert_type.as_deref(), - ); + for (dependency_key, dependency) in document.dependencies() { diagnose_dependency( &mut diagnostics, - &snapshot.documents, - &snapshot.cache_metadata, - &dependency.maybe_type, - dependency.is_dynamic, - dependency.maybe_assert_type.as_deref(), + snapshot, + specifier, + &dependency_key, + &dependency, ); } } @@ -880,15 +957,18 @@ mod tests { use crate::lsp::config::Settings; use crate::lsp::config::SpecifierSettings; use crate::lsp::config::WorkspaceSettings; + use crate::lsp::documents::Documents; use crate::lsp::documents::LanguageId; use crate::lsp::language_server::StateSnapshot; use std::path::Path; use std::path::PathBuf; + use std::sync::Arc; use test_util::TempDir; fn mock_state_snapshot( fixtures: &[(&str, &str, i32, LanguageId)], location: &Path, + maybe_import_map: Option<(&str, &str)>, ) -> StateSnapshot { let mut documents = Documents::new(location); for (specifier, source, version, language_id) in fixtures { @@ -901,8 +981,17 @@ mod tests { (*source).into(), ); } + let maybe_import_map = maybe_import_map.map(|(base, json_string)| { + let base_url = ModuleSpecifier::parse(base).unwrap(); + let result = import_map::parse_from_json(&base_url, json_string).unwrap(); + if !result.diagnostics.is_empty() { + panic!("unexpected import map diagnostics"); + } + Arc::new(result.import_map) + }); StateSnapshot { documents, + maybe_import_map, ..Default::default() } } @@ -924,9 +1013,11 @@ mod tests { fn setup( temp_dir: &TempDir, sources: &[(&str, &str, i32, LanguageId)], + maybe_import_map: Option<(&str, &str)>, ) -> (StateSnapshot, PathBuf) { let location = temp_dir.path().join("deps"); - let state_snapshot = mock_state_snapshot(sources, &location); + let state_snapshot = + mock_state_snapshot(sources, &location, maybe_import_map); (state_snapshot, location) } @@ -945,6 +1036,7 @@ let c: number = "a"; 1, LanguageId::TypeScript, )], + None, ); let snapshot = Arc::new(snapshot); let ts_server = TsServer::new(Default::default()); @@ -969,7 +1061,7 @@ let c: number = "a"; .await .unwrap(); assert_eq!(get_diagnostics_for_single(diagnostics).len(), 4); - let diagnostics = generate_deps_diagnostics( + let diagnostics = generate_deno_diagnostics( &snapshot, &enabled_config, Default::default(), @@ -1010,7 +1102,7 @@ let c: number = "a"; .await .unwrap(); assert_eq!(get_diagnostics_for_single(diagnostics).len(), 0); - let diagnostics = generate_deps_diagnostics( + let diagnostics = generate_deno_diagnostics( &snapshot, &disabled_config, Default::default(), @@ -1039,6 +1131,7 @@ let c: number = "a"; 1, LanguageId::TypeScript, )], + None, ); let snapshot = Arc::new(snapshot); let ts_server = TsServer::new(Default::default()); @@ -1053,4 +1146,128 @@ let c: number = "a"; // should be none because it's cancelled assert_eq!(diagnostics.len(), 0); } + + #[tokio::test] + async fn test_deno_diagnostics_with_import_map() { + let temp_dir = TempDir::new(); + let (snapshot, _) = setup( + &temp_dir, + &[ + ("file:///std/testing/asserts.ts", "export function assert() {}", 1, LanguageId::TypeScript), + ("file:///a/file.ts", "import { assert } from \"../std/testing/asserts.ts\";\n\nassert();\n", 1, LanguageId::TypeScript), + ], + Some(("file:///a/import-map.json", r#"{ + "imports": { + "/~/std/": "../std/" + } + }"#)), + ); + let config = mock_config(); + let token = CancellationToken::new(); + let actual = generate_deno_diagnostics(&snapshot, &config, token).await; + assert_eq!(actual.len(), 2); + for (specifier, _, diagnostics) in actual { + match specifier.as_str() { + "file:///std/testing/asserts.ts" => { + assert_eq!(json!(diagnostics), json!([])) + } + "file:///a/file.ts" => assert_eq!( + json!(diagnostics), + json!([ + { + "range": { + "start": { + "line": 0, + "character": 23 + }, + "end": { + "line": 0, + "character": 50 + } + }, + "severity": 4, + "code": "import-map-remap", + "source": "deno", + "message": "The import specifier can be remapped to \"/~/std/testing/asserts.ts\" which will resolve it via the active import map.", + "data": { + "from": "../std/testing/asserts.ts", + "to": "/~/std/testing/asserts.ts" + } + } + ]) + ), + _ => unreachable!("unexpected specifier {}", specifier), + } + } + } + + #[test] + fn test_get_code_action_import_map_remap() { + let specifier = ModuleSpecifier::parse("file:///a/file.ts").unwrap(); + let result = DenoDiagnostic::get_code_action(&specifier, &lsp::Diagnostic { + range: lsp::Range { + start: lsp::Position { line: 0, character: 23 }, + end: lsp::Position { line: 0, character: 50 }, + }, + severity: Some(lsp::DiagnosticSeverity::HINT), + code: Some(lsp::NumberOrString::String("import-map-remap".to_string())), + source: Some("deno".to_string()), + message: "The import specifier can be remapped to \"/~/std/testing/asserts.ts\" which will resolve it via the active import map.".to_string(), + data: Some(json!({ + "from": "../std/testing/asserts.ts", + "to": "/~/std/testing/asserts.ts" + })), + ..Default::default() + }); + assert!(result.is_ok()); + let actual = result.unwrap(); + assert_eq!( + json!(actual), + json!({ + "title": "Update \"../std/testing/asserts.ts\" to \"/~/std/testing/asserts.ts\" to use import map.", + "kind": "quickfix", + "diagnostics": [ + { + "range": { + "start": { + "line": 0, + "character": 23 + }, + "end": { + "line": 0, + "character": 50 + } + }, + "severity": 4, + "code": "import-map-remap", + "source": "deno", + "message": "The import specifier can be remapped to \"/~/std/testing/asserts.ts\" which will resolve it via the active import map.", + "data": { + "from": "../std/testing/asserts.ts", + "to": "/~/std/testing/asserts.ts" + } + } + ], + "edit": { + "changes": { + "file:///a/file.ts": [ + { + "range": { + "start": { + "line": 0, + "character": 23 + }, + "end": { + "line": 0, + "character": 50 + } + }, + "newText": "\"/~/std/testing/asserts.ts\"" + } + ] + } + } + }) + ); + } } diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 05d23bf0088415..2e787134b2d93d 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -84,6 +84,7 @@ pub struct StateSnapshot { pub assets: AssetsSnapshot, pub cache_metadata: cache::CacheMetadata, pub documents: Documents, + pub maybe_import_map: Option>, pub root_uri: Option, } @@ -425,6 +426,7 @@ impl Inner { assets: self.assets.snapshot(), cache_metadata: self.cache_metadata.clone(), documents: self.documents.clone(), + maybe_import_map: self.maybe_import_map.clone(), root_uri: self.config.root_uri.clone(), }) } From 33e64d7eab79b6cbdb9cc8e9853e8a763cdfa3b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Thu, 14 Jul 2022 17:39:12 +0200 Subject: [PATCH 09/16] fix tests --- cli/tests/testdata/import_meta.ts | 16 ++++++---------- cli/tests/testdata/import_meta.ts.out | 3 +-- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/cli/tests/testdata/import_meta.ts b/cli/tests/testdata/import_meta.ts index d7af3eca46a684..00aa70e70eb5ff 100644 --- a/cli/tests/testdata/import_meta.ts +++ b/cli/tests/testdata/import_meta.ts @@ -8,23 +8,19 @@ console.log( "Resolving https://example.com/rewrite from import map", import.meta.resolve("https://example.com/rewrite"), ); -console.log( - "Resolving https://example.com/rewrite from import map", - import.meta.resolve("https://example.com/rewrite"), -); console.log( "Resolving without a value from import map", import.meta.resolve(), ); -console.log( - "Resolving undefined from import map", - import.meta.resolve("https://example.com/PASS-undefined"), -); console.log( "Resolving 1 from import map", - import.meta.resolve("https://example.com/PASS-1"), + import.meta.resolve(1), ); console.log( "Resolving null from import map", - import.meta.resolve("https://example.com/PASS-null"), + import.meta.resolve(null), +); +console.log( + "Resolving object from import map", + import.meta.resolve({}), ); diff --git a/cli/tests/testdata/import_meta.ts.out b/cli/tests/testdata/import_meta.ts.out index c8c43da79995e2..a431f61df7bb4b 100644 --- a/cli/tests/testdata/import_meta.ts.out +++ b/cli/tests/testdata/import_meta.ts.out @@ -3,8 +3,7 @@ import_meta [WILDCARD]import_meta.ts true Resolving ./foo.js file:///[WILDCARD]/foo.js Resolving bare from import map https://example.com/ Resolving https://example.com/rewrite from import map https://example.com/rewritten -Resolving https://example.com/rewrite from import map https://example.com/rewritten Resolving without a value from import map https://example.com/PASS-undefined -Resolving undefined from import map https://example.com/PASS-undefined Resolving 1 from import map https://example.com/PASS-1 Resolving null from import map https://example.com/PASS-null +Resolving object from import map https://example.com/PASS-object From 3f9ff745a2cf260b61e01a6028addd110b8dc71c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Sun, 17 Jul 2022 16:39:16 +0200 Subject: [PATCH 10/16] reset CI From 45a28ab0dfec52d0d6d365b906179b8f48a51065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Mon, 18 Jul 2022 01:17:45 +0200 Subject: [PATCH 11/16] use own property --- core/bindings.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/core/bindings.rs b/core/bindings.rs index a55d3b918e90e9..ab670dcb551222 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -272,6 +272,17 @@ pub extern "C" fn host_initialize_import_meta_object_callback( let main_val = v8::Boolean::new(scope, info.main); meta.create_data_property(scope, main_key.into(), main_val.into()); + // Set the referrer in an own property, so it can be later retrieved in + // `import.meta.resolve()`. We're not using `import.meta.url` because it's a + // writable property and users might overwrite it. + let internal_refferer_key = + v8::String::new(scope, "internalReferrer").unwrap(); + meta.define_own_property( + scope, + internal_refferer_key.into(), + url_val.into(), + v8::READ_ONLY + v8::DONT_ENUM + v8::DONT_DELETE, + ); let resolve_key = v8::String::new(scope, "resolve").unwrap(); let val = v8::Function::new(scope, import_meta_resolve).unwrap(); val.set_name(resolve_key); @@ -295,8 +306,11 @@ fn import_meta_resolve( let specifier = maybe_arg_str.unwrap(); let referrer = { let receiver = args.this(); - let url_key = v8::String::new(tc_scope, "url").unwrap(); - let url_prop = receiver.get(tc_scope, url_key.into()).unwrap(); + let internal_refferer_key = + v8::String::new(tc_scope, "internalReferrer").unwrap(); + let url_prop = receiver + .get(tc_scope, internal_refferer_key.into()) + .unwrap(); url_prop.to_rust_string_lossy(tc_scope) }; let module_map_rc = JsRuntime::module_map(tc_scope); From f8874423b8cea46efd6bc239dce98f0e45439c3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Mon, 18 Jul 2022 02:43:03 +0200 Subject: [PATCH 12/16] typo --- core/bindings.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/bindings.rs b/core/bindings.rs index ab670dcb551222..2da240e77c7e39 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -275,11 +275,11 @@ pub extern "C" fn host_initialize_import_meta_object_callback( // Set the referrer in an own property, so it can be later retrieved in // `import.meta.resolve()`. We're not using `import.meta.url` because it's a // writable property and users might overwrite it. - let internal_refferer_key = + let internal_referrer_key = v8::String::new(scope, "internalReferrer").unwrap(); meta.define_own_property( scope, - internal_refferer_key.into(), + internal_referrer_key.into(), url_val.into(), v8::READ_ONLY + v8::DONT_ENUM + v8::DONT_DELETE, ); @@ -306,10 +306,10 @@ fn import_meta_resolve( let specifier = maybe_arg_str.unwrap(); let referrer = { let receiver = args.this(); - let internal_refferer_key = + let internal_referrer_key = v8::String::new(tc_scope, "internalReferrer").unwrap(); let url_prop = receiver - .get(tc_scope, internal_refferer_key.into()) + .get(tc_scope, internal_referrer_key.into()) .unwrap(); url_prop.to_rust_string_lossy(tc_scope) }; From 7c013502186af0ab7546648dfd640e7333c76bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Mon, 18 Jul 2022 15:42:46 +0200 Subject: [PATCH 13/16] use private property --- core/bindings.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/core/bindings.rs b/core/bindings.rs index 481b9fb6c8951b..b98f084eab0c9e 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -272,17 +272,13 @@ pub extern "C" fn host_initialize_import_meta_object_callback( let main_val = v8::Boolean::new(scope, info.main); meta.create_data_property(scope, main_key.into(), main_val.into()); - // Set the referrer in an own property, so it can be later retrieved in + // Set the referrer in a private, so it can be later retrieved in // `import.meta.resolve()`. We're not using `import.meta.url` because it's a // writable property and users might overwrite it. let internal_referrer_key = v8::String::new(scope, "internalReferrer").unwrap(); - meta.define_own_property( - scope, - internal_referrer_key.into(), - url_val.into(), - v8::READ_ONLY + v8::DONT_ENUM + v8::DONT_DELETE, - ); + let p = v8::Private::new(scope, Some(internal_referrer_key)); + meta.set_private(scope, p, url_val.into()); let resolve_key = v8::String::new(scope, "resolve").unwrap(); let val = v8::Function::new(scope, import_meta_resolve).unwrap(); val.set_name(resolve_key); @@ -308,9 +304,8 @@ fn import_meta_resolve( let receiver = args.this(); let internal_referrer_key = v8::String::new(tc_scope, "internalReferrer").unwrap(); - let url_prop = receiver - .get(tc_scope, internal_referrer_key.into()) - .unwrap(); + let p = v8::Private::new(tc_scope, Some(internal_referrer_key)); + let url_prop = receiver.get_private(tc_scope, p).unwrap(); url_prop.to_rust_string_lossy(tc_scope) }; let module_map_rc = JsRuntime::module_map(tc_scope); From 6eb9c3c300eec4559b7f10066b153d3a5903ec53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Mon, 18 Jul 2022 17:17:17 +0200 Subject: [PATCH 14/16] add test for broken URL --- cli/tests/testdata/import_meta.ts | 8 ++++++++ core/bindings.rs | 22 +++++----------------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/cli/tests/testdata/import_meta.ts b/cli/tests/testdata/import_meta.ts index 00aa70e70eb5ff..37af690201d185 100644 --- a/cli/tests/testdata/import_meta.ts +++ b/cli/tests/testdata/import_meta.ts @@ -1,3 +1,5 @@ +import { assertThrows } from "../../../test_util/std/testing/asserts.ts"; + console.log("import_meta", import.meta.url, import.meta.main); import "./import_meta2.ts"; @@ -24,3 +26,9 @@ console.log( "Resolving object from import map", import.meta.resolve({}), ); +assertThrows(() => { + import.meta.resolve("too", "many", "arguments"); +}, TypeError); +assertThrows(() => { + import.meta.resolve("://malformed/url?asdf"); +}, TypeError); diff --git a/core/bindings.rs b/core/bindings.rs index b98f084eab0c9e..a6104391b974b9 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -272,16 +272,10 @@ pub extern "C" fn host_initialize_import_meta_object_callback( let main_val = v8::Boolean::new(scope, info.main); meta.create_data_property(scope, main_key.into(), main_val.into()); - // Set the referrer in a private, so it can be later retrieved in - // `import.meta.resolve()`. We're not using `import.meta.url` because it's a - // writable property and users might overwrite it. - let internal_referrer_key = - v8::String::new(scope, "internalReferrer").unwrap(); - let p = v8::Private::new(scope, Some(internal_referrer_key)); - meta.set_private(scope, p, url_val.into()); + let builder = + v8::FunctionBuilder::new(import_meta_resolve).data(url_val.into()); + let val = v8::FunctionBuilder::::build(builder, scope).unwrap(); let resolve_key = v8::String::new(scope, "resolve").unwrap(); - let val = v8::Function::new(scope, import_meta_resolve).unwrap(); - val.set_name(resolve_key); meta.set(scope, resolve_key.into(), val.into()); } @@ -301,11 +295,7 @@ fn import_meta_resolve( } let specifier = maybe_arg_str.unwrap(); let referrer = { - let receiver = args.this(); - let internal_referrer_key = - v8::String::new(tc_scope, "internalReferrer").unwrap(); - let p = v8::Private::new(tc_scope, Some(internal_referrer_key)); - let url_prop = receiver.get_private(tc_scope, p).unwrap(); + let url_prop = args.data().unwrap(); url_prop.to_rust_string_lossy(tc_scope) }; let module_map_rc = JsRuntime::module_map(tc_scope); @@ -323,9 +313,7 @@ fn import_meta_resolve( rv.set(resolved_val); } Err(err) => { - let message = v8::String::new(tc_scope, &err.to_string()).unwrap(); - let exception = v8::Exception::error(tc_scope, message); - tc_scope.throw_exception(exception); + throw_type_error(tc_scope, &err.to_string()); } }; } From d9c5bc014637b1a37edfe358c37824d8bcd038f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Mon, 18 Jul 2022 17:53:46 +0200 Subject: [PATCH 15/16] don't use TryCatch --- core/bindings.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/core/bindings.rs b/core/bindings.rs index a6104391b974b9..6ec758c97c6efd 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -288,32 +288,28 @@ fn import_meta_resolve( return throw_type_error(scope, "Invalid arguments"); } - let tc_scope = &mut v8::TryCatch::new(scope); - let maybe_arg_str = args.get(0).to_string(tc_scope); + let maybe_arg_str = args.get(0).to_string(scope); if maybe_arg_str.is_none() { - return throw_type_error(tc_scope, "Invalid arguments"); + return throw_type_error(scope, "Invalid arguments"); } let specifier = maybe_arg_str.unwrap(); let referrer = { let url_prop = args.data().unwrap(); - url_prop.to_rust_string_lossy(tc_scope) + url_prop.to_rust_string_lossy(scope) }; - let module_map_rc = JsRuntime::module_map(tc_scope); + let module_map_rc = JsRuntime::module_map(scope); let loader = { let module_map = module_map_rc.borrow(); module_map.loader.clone() }; - match loader.resolve( - &specifier.to_rust_string_lossy(tc_scope), - &referrer, - false, - ) { + match loader.resolve(&specifier.to_rust_string_lossy(scope), &referrer, false) + { Ok(resolved) => { - let resolved_val = serde_v8::to_v8(tc_scope, resolved.as_str()).unwrap(); + let resolved_val = serde_v8::to_v8(scope, resolved.as_str()).unwrap(); rv.set(resolved_val); } Err(err) => { - throw_type_error(tc_scope, &err.to_string()); + return throw_type_error(scope, &err.to_string()); } }; } From 75d9519e9f5082e9fb760b73856d5c6349fac3e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Mon, 18 Jul 2022 17:55:13 +0200 Subject: [PATCH 16/16] lint --- core/bindings.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/bindings.rs b/core/bindings.rs index 6ec758c97c6efd..f9fd1f402fdb3a 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -309,7 +309,7 @@ fn import_meta_resolve( rv.set(resolved_val); } Err(err) => { - return throw_type_error(scope, &err.to_string()); + throw_type_error(scope, &err.to_string()); } }; }