-
Notifications
You must be signed in to change notification settings - Fork 11
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
Eager or Lazy import.meta construction #80
Comments
I'm still very confused why we'd want to expose, pre-evaluation, whether a module references |
Because for most modules it is trivially statically apparent that they do not, and there is benefit to being able to avoid creating it for the vast majority of modules that do not need it. |
Can't it be represented by, instead of an object, a thunk? ie, a function that's called the first time it's needed, creates and returns the object, and cached forever after that? |
How does this differ from Lazy (option 3)? |
ah, i suppose that's the same thing then, hmm :-/ the information i'd prefer to avoid exposing is "whether a module uses |
Lazy has the problem that user code then interleaves at the point of evaluating the As for API fragility, eager makes the dependency only on that static text of the module, whereas lazy makes it depend on what happens dynamically at runtime, which can be data dependent. |
Right - but the static text of the module is, just like the source of a function, not supposed to be reliably observable from without, for the same reasons. |
I’m sympathetic to both interleaving (Lazy) and breaking change hazards (Prior, Eager). Can I ask @erights and @ljharb to contrive concrete examples? The interleaving hazard takes the form below, where the source is able to tease
The breaking change hazard will always consist of a pair of versions of the same module source, one with and the other without I imagine there’s another class of hazard, where something about this design increases the probability of a defect in a virtualized module system. That’s worth talking about too. |
How is Like a module could change it's imports and a loader would need to be prepared to handle that, so why would |
That’s a really good point, and a wider potential concern for this proposal. |
From a high level I'd be fine with either a lazy api or passing the object into the constructor. A hook that is just called immediately in the constructor seems a bit pointless/confusing in comparison. I'd also be against trying to be super clever about whether a module contains |
A hook, even if called immediately, allows to properly replicate the behavior of every host. Just passing an object to the constructor doesn't allow, for example, to freeze |
At the September 21, 2022 SES Strategy call we discussed three options for timing the construction of
import.meta
for a virtual module.needsImportMeta
property that indicates whether the source contains AST nodes for eitherimport.meta
oreval
, and the module handler passed toModule(source, handler)
must have a pre-builtimportMeta
property that will be used by that module if it ever evaluates animport.meta
expression.Module(source, handler)
constructor that it must callhandler.importMetaHook()
to construct animport.meta
and capture it on the Module instance’s [[ImportMeta]] internal slot before the constructor returns.importMetaHook()
that will be called upon the first evaluation of animport.meta
expression, capturing [[ImportMeta]] on the Module instance internal slot for every subsequent evaluation ofimport.meta
.Commentary:
Lazy may or may not pose either a reentrance hazard. The virtual module is vulnerable to faulty arrangement by whomever constructs the
Module
regardless, but the question is whether there is undue risk if we allow the host to execute arbitrary code in the context of the virtual module.In particular, of the participants of the SES call, @nicolo-ribaudo and @erights agree that we take as a guiding principle in this design that hosts and virtual hosts should be given equivalent power, so if a host may execute on the stack of
import.meta
and also may have side-effects as a consequence of evaluatingimport.meta
, it stands to reason that a virtual host should be allowed the same. However, if 262 constrains hosts to have no observable side-effects uponimport.meta
, virtual hosts mustn’t be able to execute arbitrary code at that time.Whether the import meta object is constructed at all is not equivalent between these two proposals. There are cases where eager is necessarily over-eager, since it must speculate on whether
eval
will result in evaluation ofimport.meta
. We doubt that the difference in behavior will be germane to the performance motivations for lazy construction on Node.js. There will be very few cases where a module uses eitherimport.meta
oreval
, much fewer for both.The choice between eager and prior construction is a matter of developer ergonomics.
The text was updated successfully, but these errors were encountered: