Skip to content

Editorial: Lazily compute the list of [[Exports]] of a module namespace - #68

Closed
nicolo-ribaudo wants to merge 2 commits into
tc39:mainfrom
nicolo-ribaudo:lazy-exports-list
Closed

Editorial: Lazily compute the list of [[Exports]] of a module namespace#68
nicolo-ribaudo wants to merge 2 commits into
tc39:mainfrom
nicolo-ribaudo:lazy-exports-list

Conversation

@nicolo-ribaudo

@nicolo-ribaudo nicolo-ribaudo commented Jun 19, 2025

Copy link
Copy Markdown
Member

A goal of the proposal is that implementations can, under some circumstances, easily implement lazy loading of deferred modules (when they know that they don't have syntax errors or transitive async dependencies).

While trying to actually implement an example of that, I found a problem: even though it's not user-exposed, the spec eagerly reads the list of exports in GetModuleNamespace. It requires some non-trivial changes to actually do it lazily, and this PR does it directly in the spec so that implementations are not forced to diverge.

Collection of the list of exports in a module (for the module namespace) is now centralized in GetModuleExportsList, including removal of the "then" key for deferred namespaces.

Closes #69.


cc @dminor. This is probably relevant for the SM implementation. I'll post an example of how to do sync lazy loading in engine262 soon.

@guybedford guybedford left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Rather than making this lazy for all module namespaces, would there be any loss here to make it lazy only in the case of deferred module namespaces?

I think we have a really nice strong guarantee today that namespaces are declared upfront, and it would be a shame to "over-proxify" all namespaces when only deferred namespaces need this level of dynamism.

Making it very clear that non deferred namespaces have static semantics and keeping that invariant would be a nice property to maintain I think.

My suggestion would actually be here:

  • Rename GetModuleExportsList to GetLazyModuleExportsList
  • Still set [[Exports]] upfront for normal namespaces
  • In the exotic namespace hooks, use [[Exports]] directly for non-deferred, only calling GetLazyModuleExportsList in the deferred case.

This would make it immediately visible at the implementation level that only deferred namespaces have the dynamism.

A goal of the proposal is that implementations can, under some circumstances,
easily implement lazy loading of deferred modules (when they know that they
don't have syntax errors or transitive async dependencies).

While trying to actually implement an example of that, I found a problem: even though
it's not user-exposed, the spec eagerly reads the list of exports in GetModuleNamespace.
It requires some non-trivial changes to actually do it lazily, and this PR does it directly
in the spec so that implementations are not forced to diverge.

Collection of the list of exports in a module (for the module namespace) is now centralized
in GetModuleExportsList, including removal of the `"then"` key for deferred namespaces.
@nicolo-ribaudo

Copy link
Copy Markdown
Member Author

@guybedford I updated the PR to still eagerly compute [[Exports]] for non-deferred namespaces.

However, I kept the GetModuleExportsList AO because adding in every single internal method of namesapce objects the "is this lazy? to this, else do that" check was a lot of visual noise that is exactly what that AO dedupes.

Now:

  • ModuleNamespaceCreate doesn't handle [[Exports]] anymore, and that logic has been moved to a new PopulateModuleNamespaceExportsList AO
  • for eager namespaces, GetModuleNamesapce will call ModuleNamespaceCreate and then immediately call PopulateModuleNamespaceExportsList. GetModuleExportsList will assert that [[Exports]] is already populated.
  • for lazy namespaces, GetModuleNamesapce will only call ModuleNamespaceCreate. GetModuleExportsList will then call PopulateModuleNamespaceExportsList if needed.

Preview: https://nicolo-ribaudo.github.io/proposal-defer-import-eval/

@nicolo-ribaudo

Copy link
Copy Markdown
Member Author

@guybedford I opened #69 as an alternative. I don't actually like making the spec more complex (like this PR does) for something that is not an observable change from ECMAScript code.

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.

2 participants