Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: resolve node builtin module without node: scheme #295

Merged
merged 10 commits into from
Sep 28, 2023

Conversation

kt3k
Copy link
Member

@kt3k kt3k commented Sep 20, 2023

part of denoland/deno#20566

This PR updates the resolution of bare specifiers. If the module specifier is node builtin module as a bare specifier, resolve it as node:<module_name>. Also it prints the warning message like Warning: Resolving "path" as "node:path". If you want to use a built-in Node module, add a "node:" prefix.

@kt3k kt3k requested a review from dsherret September 20, 2023 16:00
@kt3k
Copy link
Member Author

kt3k commented Sep 21, 2023

Tested with the below change in Deno CLI repo:

index 36dccab10..6bbdc96c0 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -49,16 +49,16 @@ deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "dep_gra
 deno_cache_dir = "=0.6.0"
 deno_config = "=0.3.1"
 deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
-deno_doc = "=0.67.0"
-deno_emit = "=0.28.0"
-deno_graph = "=0.55.0"
+deno_doc = { path = "../../deno_doc" }
+deno_emit = { path = "../../deno_emit/rs-lib" }
+deno_graph = { path = "../../deno_graph" }
 deno_lint = { version = "=0.51.0", features = ["docs"] }
 deno_lockfile.workspace = true
 deno_npm.workspace = true
 deno_runtime = { workspace = true, features = ["dont_create_runtime_snapshot", "exclude_runtime_main_js", "include_js_files_for_snapshotting"] }
 deno_semver.workspace = true
 deno_task_shell = "=0.13.2"
-eszip = "=0.53.0"
+eszip = { path = "../../eszip" }
 napi_sym.workspace = true
 
 async-trait.workspace = true

It works like the below:

$ cat a.js                       
import fs from "fs";
import path from "path";
console.log(fs.write);
$ ./target/debug/deno run a.js 
Warning: Resolving "fs" as "node:fs". If you want to use a built-in Node module, add a "node:" prefix.
Warning: Resolving "path" as "node:path". If you want to use a built-in Node module, add a "node:" prefix.
[Function: write]

Copy link
Member

@dsherret dsherret left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kt3k looks mostly good, but we need to make some changes.

src/module_specifier.rs Outdated Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
src/module_specifier.rs Outdated Show resolved Hide resolved
@kt3k
Copy link
Member Author

kt3k commented Sep 26, 2023

Now this change uses is_builtin_node_module_name and on_resolve_bare_builtin_node_module from NpmResolver trait for checking builtin node module and printing warnings.

I skipped supporting the same thing with wasm/js version as npm resolver doesn't seem configured for them.

Copy link
Member

@dsherret dsherret left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very close now. Looking good!

src/module_specifier.rs Outdated Show resolved Hide resolved
if maybe_npm_resolver.map_or(false, |npm_resolver| {
npm_resolver.is_builtin_node_module_name(specifier)
}) =>
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should move this check to a higher level in:

deno_graph/src/graph.rs

Lines 1551 to 1562 in aa9236c

fn resolve(
specifier_text: &str,
referrer_range: Range,
maybe_resolver: Option<&dyn Resolver>,
) -> Resolution {
let response = if let Some(resolver) = maybe_resolver {
resolver.resolve(specifier_text, &referrer_range.specifier)
} else {
resolve_import(specifier_text, &referrer_range.specifier)
.map_err(|err| err.into())
};
Resolution::from_resolve_result(response, specifier_text, referrer_range)

#296 will make this easier.

That way this behaviour isn't dependent on an implentor of the Resolver calling this resolve_import function and needing access to the npm resolver. Basically, if a user provides an NpmResolver to deno_graph then they'll get this behaviour.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the check of bare builtin node specifier. Now it is checked after resolver.resolve is applied.

lib/lib.rs Outdated
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we discussed making this conditional in the meeting, but maybe making it "just work" is ok to do in a patch release of Deno. It would be less work and make stuff work sooner. cc @bartlomieju

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's okay for me 👍

@kt3k kt3k force-pushed the resolve-base-node-native-modules branch from 0d1b184 to f75e8d3 Compare September 27, 2023 09:43
Copy link
Member

@dsherret dsherret left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! LGTM!

src/graph.rs Outdated
if maybe_mod_name.is_some() {
npm_resolver.on_resolve_bare_builtin_node_module(specifier_text);
return Resolution::from_resolve_result(
Ok(maybe_specifier.unwrap()),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, the .unwrap() could be removed by using .filter on the result of ModuleSpecifier::parse(&format!("node:{}", specifier_text)).ok() when npm_resolver.resolve_builtin_node_module(s).ok().flatten().is_some()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, the .unwrap() could be removed by using .filter on the result of ModuleSpecifier::parse(&format!("node:{}", specifier_text)).ok()

I didn't get what this exactly means.., but removed the usage of .unwrap() in a different way. 4ebda53

@kt3k
Copy link
Member Author

kt3k commented Sep 27, 2023

@dsherret Thank you for your review! I'll land this and release it as v0.56.0 tomorrow my time (and will continue working on dependent crates, such as eszip, deno_emit, deno_doc, etc).

@kt3k kt3k merged commit 3d51f4f into denoland:main Sep 28, 2023
4 checks passed
@kt3k kt3k deleted the resolve-base-node-native-modules branch September 28, 2023 06:12
@kt3k
Copy link
Member Author

kt3k commented Sep 28, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants