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: add --compat flag to provide built-in Node modules #12293

Merged
merged 13 commits into from
Oct 4, 2021

Conversation

bartlomieju
Copy link
Member

@bartlomieju bartlomieju commented Oct 1, 2021

Currently blocked on denoland/import_map#11

Towards #12295

cli/node_compat.rs Outdated Show resolved Hide resolved
@ry ry mentioned this pull request Oct 2, 2021
7 tasks
@bartlomieju bartlomieju changed the title [WIP] feat: add --node-compat flag to provide built-in Node modules [WIP] feat: add --compat flag to provide built-in Node modules Oct 2, 2021
@bartlomieju bartlomieju changed the title [WIP] feat: add --compat flag to provide built-in Node modules feat: add --compat flag to provide built-in Node modules Oct 2, 2021
@bartlomieju bartlomieju requested a review from ry October 2, 2021 14:07
Copy link
Member

@ry ry left a comment

Choose a reason for hiding this comment

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

LGTM - quick and dirty, that's how I like MVPs.

}
};
let node_builtins = crate::compat::get_mapped_node_builtins();
let diagnostics = import_map.update_imports(node_builtins)?;
Copy link
Contributor

Choose a reason for hiding this comment

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

What happens if some already has entries for some/all of them?

Copy link
Member Author

Choose a reason for hiding this comment

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

A diagnostic is printed out to the terminal, like so:

❯ cargo run -- run --compat --unstable -A --import-map import-map.json cli/tests/testdata/compat/fs_promises.js
    Finished dev [unoptimized + debuginfo] target(s) in 0.38s
     Running `target/debug/deno run --compat --unstable -A --import-map import-map.json cli/tests/testdata/compat/fs_promises.js`
  - "fs" already exists and is mapped to Some(Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("example.com")), port: None, path: "/1", query: None, fragment: None })

I just noticed that the output is broken and will fix it before landing the PR, should be

  - "fs" already exists and is mapped to "https://example.com/1"

Copy link
Member Author

Choose a reason for hiding this comment

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

Added a test: compat::existing_import_map

Copy link
Member Author

Choose a reason for hiding this comment

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

Finally shows up as:

The were problems adding Node built-ins to import map:
  - "fs/promises" already exists and is mapped to "[WILDCARD]non_existent_file.js"

Suggestions welcome

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess it is still unclear to the user what the state is or what action they should take. Is it really a problem? If it is a problem, what should a user do about it to resolve it?

Copy link
Member Author

Choose a reason for hiding this comment

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

I clarified it even further:

Some Node built-ins were not added to the import map:
  - "fs/promises" already exists and is mapped to "[WILDCARD]non_existent_file.js"
If you want to use Node built-ins provided by Deno remove listed specifiers from "imports" mapping in the import map file.

Copy link
Contributor

Choose a reason for hiding this comment

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

Cool

@bartlomieju
Copy link
Member Author

Before landing I think we should add aliases for node: prefix as per: https://nodejs.org/api/esm.html#esm_node_imports

Copy link
Contributor

@kitsonk kitsonk left a comment

Choose a reason for hiding this comment

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

I am all for moving fast, but a few concerns about this PR:

  • As it stands, this is something that takes something that is either not used by the user or explicitly used by a user and modifies it in an opaque way. Not only is this bad for the user (I expected x behaviour but suddenly it does y), but there is no way to fix it.
  • As it stands, this doesn't do anything that the user can't do a runtime. We have been endlessly debating that the CLI should do less and that we shouldn't introduce things (or even remove things) that make it inconsistent with Deploy. Deploy could easily support impart maps, which if generated could easily be used without introducing a --compat flag for Deploy. So why does this need to be a flag in the CLI?
  • This creates more problems like --unstable in that authors of code would need to tell consumers to run it. It all being in an import map doesn't solve that problem specifically, but we need to address "import map composition" anyways, and it is far easier to address if there isn't some code behind the scenes modifying it in an opaque way.
  • There is no support in the lsp for this. Meaning someone using this flag has no way to set it in the editor, meaning that the behaviour is quite a bit different.

We should really consider this as a standalone, runtime tool first, getting experience with the problems and issues encountered before we bake it into the CLI, IMO.

It would be great if we could talk about these things in our design meeting, before we commit to delivering them.


for module in SUPPORTED_MODULES {
// TODO(bartlomieju): this is unversioned, and should be fixed to use latest stable?
let module_url = format!("https://deno.land/std/node/{}.ts", module);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this not going to print the X-Deno-Warning text every time the user caches it for the first time, with no clue as how to fix it?

Copy link
Member

Choose a reason for hiding this comment

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

Yep - we can worry about this later.

@kitsonk
Copy link
Contributor

kitsonk commented Oct 2, 2021

We should really consider this as a standalone, runtime tool first, getting experience with the problems and issues encountered before we bake it into the CLI, IMO.

Which if it were, you would get lsp support immediately.

@ry
Copy link
Member

ry commented Oct 2, 2021

So why does this need to be a flag in the CLI?

@kitsonk to make it fast and easy.

So we've got a couple todos:

  • "node:" prefixes. I think this could as well be done in follow up PR. Most code does not use these prefixes.
  • Figure out X-Deno-Warning and figure out if we should tag std URLs. Could be done in follow up.
  • LSP support. Could be done in follow up.

Copy link
Member

@piscisaureus piscisaureus left a comment

Choose a reason for hiding this comment

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

I have reservations about the use of a flag, long term.

However I do believe this is the right approach for making more of the existing node.js ecosystem available to Deno users.

@bartlomieju bartlomieju merged commit f1d3a17 into denoland:main Oct 4, 2021
@bartlomieju bartlomieju deleted the node_builtins branch October 4, 2021 23:35
@wojpawlik
Copy link

What's the advantage of --compat over hypothetical --import-map=https://deno.land/std/node/import_map.json?

Before landing I think we should add aliases for node: prefix as per: nodejs.org/api/esm.html#esm_node_imports

I agree! Those could even be available without any flags.

So why does this need to be a flag in the CLI?

to make it fast and easy.

I believe this is a mistake. Deno used to be very deliberate when adding features.

@bartlomieju
Copy link
Member Author

What's the advantage of --compat over hypothetical --import-map=https://deno.land/std/node/import_map.json?

--compat adds relevant entries to the import map on the fly, having https://deno.land/std/node/import_map.json means you need to manually construct import map.

I agree! Those could even be available without any flags.

Why would they be available without a flag? We support only http:, https: and file: schemes by default, given that node: is not really popular in Node.js ecosystem I see no point in supporting that without a flag.

I believe this is a mistake. Deno used to be very deliberate when adding features.

Thanks for the feedback. This is an experiment, it might never ship.

@wojpawlik
Copy link

having https://deno.land/std/node/import_map.json means you need to manually construct import map.

Not if you allow to reference one import map within another, or repeat --import-map.

Why would they be available without a flag?

Because they'd create a subset of ESM that could be run in both runtimes with no changes or flags, without conflicting with anything.

node: is not really popular

Node.js uses it in docs now, so I'd expect that to start changing once Node 14 hits EOL. And Deno support could boost adoption.

@bartlomieju
Copy link
Member Author

having https://deno.land/std/node/import_map.json means you need to manually construct import map.

Not if you allow to reference one import map within another, or repeat --import-map.

Import map spec doesn't allow that right now, if it changes this is definitely something to consider.

Why would they be available without a flag?

Because they'd create a subset of ESM that could be run in both runtimes with no changes or flags, without conflicting with anything.

Sure, but I haven't seen any libraries using node: prefix right now, if that changes and becomes popular we can consider that.

node: is not really popular

Node.js uses it in docs now, so I'd expect that to start changing once Node 14 hits EOL. And Deno support could boost adoption.

Sure, so we'll support that via the --compat flag right now.

@wojpawlik
Copy link

Sure, so we'll support that via the --compat flag right now.

Fair enough. Please mark the flag as unstable tho, so it can be removed without notice as soon as it's no longer needed.

@cmoog
Copy link
Contributor

cmoog commented Oct 12, 2021

quick and dirty, that's how I like MVPs.

This sets a bad precedent for the Deno CLI as a testing ground for experiments. Can you imagine the Go team rushing quick and dirty features into the Go CLI?

We should really consider this as a standalone, runtime tool first, getting experience with the problems and issues encountered before we bake it into the CLI, IMO.

^^ agreed.

@dsherret
Copy link
Member

This sets a bad precedent for the Deno CLI as a testing ground for experiments. Can you imagine the Go team rushing quick and dirty features into the Go CLI?

@cmoog please note that this is an unstable feature. Additionally, it has been discussed endlessly—it was not rushed and it will be developed/improved more over time.

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.

None yet

7 participants