You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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.
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.
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.
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
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.
Reacted by Luca Casonato, Jordan Harband, Ednei Alves dos Santos and Pelle Wessman
@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?
@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).
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.
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.
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.
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.
Activity
ljharb commentedon 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 commentedon Jul 7, 2023
In Deno,
import.meta.mainis 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 whatimport.meta.mainmarks, and it would work much likerequire.main === modulein CommonJS.(Btw, in the meeting @lucacasonato mentioned that in Deno,
import.meta.mainwas 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.mainis 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.mainas 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.jsonsupports 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 howpackage.jsonworks in Node.js, and it doesn't necessarily apply to other runtimes.devsnek commentedon Jul 7, 2023
Just to clarify, the reason I dislike
import.meta.mainis 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 usepackage.jsonbut there are alternatives. In the context of wintercg I think my suggestion would be doinglocation.href === import.meta.url. This removes the specific module instance from the calculation and therefore resolves the ambiguity.lucacasonato commentedon Jul 7, 2023
I fail to see how this is any different from
import.meta.main. In what cases would this return a different result?Also
location.hrefin no runtime (except FF in very weird cases) can point to afile:///URL. Node does not havelocation, and Deno never sets location without manual user intervention (--location).I think we should standardize the
import.meta.mainproperty totruefor modules that are unambiguously the entrypoint of an agent cluster. This would mean:deno run main.js: it istrueinmain.jsdeno run main.jsdynamically importingside.js: it istrueinmain.js,falseinside.jsdeno test main_test.js side_test.js: it is false in bothdeno run, thennew Worker: it is false in all modules in a workernode index.mjs: it istrueinindex.mjsnode index.cjs: it isfalsein all modulesnode index.cjsdynamically importingindex.mjs: it isfalsein all modulesnodethennew Worker(with worker threads): it is false in all modules in the workernode --test main_test.js side_test.js: it isfalsein all modulesworkerd run index.js: it istruein index.jsfalselittledan commentedon Jul 7, 2023
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 commentedon 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 commentedon 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 commentedon 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 commentedon Jul 25, 2023
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.Add requirements for ESM-supporting runtimes
nicolo-ribaudo commentedon Jul 25, 2023
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 commentedon Aug 2, 2023
mainhas 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 commentedon Dec 4, 2023
Related conversation in TC39 forums:
import.meta.isEntryto detect top-level root module(s)jasnell commentedon Dec 7, 2023
We now have the
import.metaregistry (https://github.com/wintercg/import-meta-registry). I would suggest thatimport.meta.urlandimport.meta.resolve()are the only two we should specifically address in the common minimum spec.