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

Add import.meta #46

Open
andreubotella opened this issue Jul 6, 2023 · 13 comments · May be fixed by #49
Open

Add import.meta #46

andreubotella opened this issue Jul 6, 2023 · 13 comments · May be fixed by #49

Comments

@andreubotella
Copy link
Member

In today's WinterCG meeting we agreed to add import.meta to the common minimum API, including the web's url property and resolve method, but also Deno's main property.

@ljharb
Copy link
Member

ljharb commented Jul 6, 2023

I missed the meeting, but what exactly is import.meta.main? node had a lot of discussion about why it could be harmful to add something like that; I'd love to understand better.

@andreubotella
Copy link
Member Author

andreubotella commented Jul 7, 2023

In Deno, import.meta.main is a boolean property that is true for the module that was loaded as the entrypoint to the process (or to the isolate/agent, see below). In Deno you don't have scripts, only modules, and therefore some module needs to be the one invoked by the CLI call. That is what import.meta.main marks, and it would work much like require.main === module in CommonJS.

(Btw, in the meeting @lucacasonato mentioned that in Deno, import.meta.main was always false in workers, such that this property being true would mean this is the entrypoint module of the process, rather than of the isolate/agent. But this turns out not to be true: import.meta.main is true for the worker's entrypoint module. I can see use cases for it working both ways (e.g. if you're the worker entrypoint, you might handle communication with the main thread), but this probably merits some extra discussion.)

Since we want to include browsers as web-interoperable runtimes, and there are WinterCG-adjacent runtimes like NativeScript that aren't server-side, the idea was to define import.meta.main as an optional property. After all, browsers can have multiple entrypoints to the module graph, but none of them is ever an entrypoint to the window. So I guess this would leave room for Node.js to not support it.

But as far as I understand, the main person who opposed adding this to Node.js was @devsnek, and their concerns were mostly about how, since package.json supports specifying both a library entrypoint (main) and a CLI entrypoint (bin), and any CLI initialization code should go on a separate CLI entrypoint. But this seems very specific to how package.json works in Node.js, and it doesn't necessarily apply to other runtimes.

@devsnek
Copy link

devsnek commented Jul 7, 2023

their concerns were mostly about how, since package.json supports specifying both a library entrypoint (main) and a CLI entrypoint (bin), and any CLI initialization code should go on a separate CLI entrypoint.

Just to clarify, the reason I dislike import.meta.main is because a module, during its lifetime, can be imported in multiple ways. When you split the binary into a separate file the usage is unambiguous. One of my suggested approaches was indeed to use package.json but there are alternatives. In the context of wintercg I think my suggestion would be doing location.href === import.meta.url. This removes the specific module instance from the calculation and therefore resolves the ambiguity.

@lucacasonato
Copy link
Member

In the context of wintercg I think my suggestion would be doing location.href === import.meta.url

I fail to see how this is any different from import.meta.main. In what cases would this return a different result?

Also location.href in no runtime (except FF in very weird cases) can point to a file:/// URL. Node does not have location, and Deno never sets location without manual user intervention (--location).


I think we should standardize the import.meta.main property to true for modules that are unambiguously the entrypoint of an agent cluster. This would mean:

  • deno run main.js: it is true in main.js
  • deno run main.js dynamically importing side.js: it is true in main.js, false in side.js
  • deno test main_test.js side_test.js: it is false in both
  • deno run, then new Worker: it is false in all modules in a worker
  • node index.mjs: it is true in index.mjs
  • node index.cjs: it is false in all modules
  • node index.cjs dynamically importing index.mjs: it is false in all modules
  • node then new Worker (with worker threads): it is false in all modules in the worker
  • node --test main_test.js side_test.js: it is false in all modules
  • workerd run index.js: it is true in index.js
  • In browsers, it is always false

@littledan
Copy link

I'm a little worried about the prospect of defining things as "normative optional". If we want to define multiple conformance classes--e.g., one for servers and one "generic" that might omit some server features--let's do that, but it should be clear which sort of implementation should try to conform to which set of things. We shouldn't define something as normative optional just because Node and Deno disagree on substance whether it's a good idea--the whole point of WinterCG is to make these sorts of environments more compatible with each other.

@ljharb
Copy link
Member

ljharb commented Jul 7, 2023

@lucacasonato if "is this the main" doesn't make sense for all wintercg runtimes - which it doesn't sound like it does for node - then it seems inappropriate for wintercg?

@devsnek
Copy link

devsnek commented Jul 7, 2023

To be very very clear I am not putting any weight into Node's official position here. I was just clarifying my opinion since I was pinged.

@lucacasonato
Copy link
Member

lucacasonato commented Jul 8, 2023

@ljharb I don't see where you got the conclusion: "which it doesn't sound like it does for node". For example, my proposal above outlines how it can make sense (exactly the same way as it does in Deno).

@andreubotella
Copy link
Member Author

I'm trying to spec this, and it's not clear how to define an agent cluster's entrypoint module in a way that excludes <script type="module"> in browsers.

andreubotella added a commit to andreubotella/proposal-common-minimum-api that referenced this issue Jul 25, 2023
This also includes specifying `import.meta.main` and allowing runtimes
to customize module loading.

Closes wintercg#46.
@andreubotella andreubotella linked a pull request Jul 25, 2023 that will close this issue
@nicolo-ribaudo
Copy link

You may add an implementation-defined "is an entry point? given a module script" algorithm with the normative requirement that, if "is an entry point? given X" returns true at any point, then `is an entry point? given Y" can only return true if X is Y. It's a bit hand-wavy, but hopefully clear enough and implementations will not diverge.

@guybedford
Copy link

main has a very specific meaning in posix in terms of an application run to completion semantic (and for JS, until the task queue is drained), alluding to that kind of definition might be possible and it clearly distinguishes browser apps which have no concept of run to completion then as well.

@trusktr
Copy link

trusktr commented Dec 4, 2023

Related conversation in TC39 forums: import.meta.isEntry to detect top-level root module(s)

@jasnell
Copy link
Contributor

jasnell commented Dec 7, 2023

We now have the import.meta registry (https://github.com/wintercg/import-meta-registry). I would suggest that import.meta.url and import.meta.resolve() are the only two we should specifically address in the common minimum spec.

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 a pull request may close this issue.

9 participants