Skip to content

ECMA-262 Normative: formalize module keying host invariant predicates and variables#59

Open
guybedford wants to merge 2 commits intomainfrom
host-formalize
Open

ECMA-262 Normative: formalize module keying host invariant predicates and variables#59
guybedford wants to merge 2 commits intomainfrom
host-formalize

Conversation

@guybedford
Copy link
Copy Markdown
Collaborator

@guybedford guybedford commented Mar 3, 2026

The host hook invariants for module loading are a very important concept in the spec and this specification extends them with support for the source phase module invariants (import(source) of a ModuleSource object).

We require that import(source) and import(url)` where URL and source point to the same module, to always return the same instance.

In order to achieve this we need to define a concept of a module key.

Currently today, the host invariant of ES Modules is not fully defined - in the sense that we do not define that import('./foo.js') and import('https://site.com/foo.js') resolve to the same module, since we do not have any concept of a module key.

This change now defines, the concept of a Canonical ModuleRequest Record, where all (referrer, moduleRequest) pairs have a single canonical ModuleRequest Record they can be related to.

By defining this as part of the host invariants, we are then able to talk in terms of module keys, laying the groundwork for source phase module keys.

In the process, we define all variables of the constraint explicitly, and then we move all predicates of the condition to the formal predicate list to ensure the explicit wording is as short as possible and this is as close as possible to a mathematical constraint as we can make it.

//cc @nicolo-ribaudo

@guybedford guybedford changed the title Editorial: formalize host invariant predicates and variables Normative: formalize host invariant predicates and variables Mar 4, 2026
@guybedford guybedford changed the title Normative: formalize host invariant predicates and variables Normative: formalize module keying host invariant predicates and variables Mar 4, 2026
@guybedford guybedford changed the base branch from module-source to main March 4, 2026 23:05
@guybedford guybedford force-pushed the host-formalize branch 3 times, most recently from 604bd28 to 62d30c3 Compare March 5, 2026 02:30
@guybedford guybedford changed the title Normative: formalize module keying host invariant predicates and variables ECMA-262 Normative: formalize module keying host invariant predicates and variables Mar 10, 2026
Copy link
Copy Markdown
Member

@nicolo-ribaudo nicolo-ribaudo left a comment

Choose a reason for hiding this comment

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

Minor comments, but it looks overall good.

Comment thread spec.emu Outdated
Comment thread spec.emu
<li>the first _referrer_ is the same as the second _referrer_;</li>
<li>ModuleRequestsEqual(the first _moduleRequest_, the second _moduleRequest_) is *true*;</li>
<li><ins>_moduleRequestKey_.[[Phase]] is equal to ~source~ (the lowest possible phase);</ins></li>
<li><ins>FinishLoadingImportedModule will return the same NormalCompletion(_module_) _result_ for all (_otherReferrer_, _otherModuleRequest_) pairs whose Canonical ModuleRequest Record is also _moduleRequestKey_;</ins></li>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Note that two normal completions containing the same module are not "the same", as spec record have identity.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Do you mean instead here spec records don't have identity?

In this case, how are we able to equate _result_ today in the host invariant at all? What is the suggestion here?

Comment thread spec.emu Outdated
Comment thread spec.emu Outdated
Comment thread spec.emu
<ul>
<li>the first _referrer_ is the same as the second _referrer_;</li>
<li>ModuleRequestsEqual(the first _moduleRequest_, the second _moduleRequest_) is *true*;</li>
<li><ins>_moduleRequestKey_.[[Phase]] is equal to ~source~ (the lowest possible phase);</ins></li>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

IIUC, _moduleRequestKey_.[[Phase]] could be ~evaluation~. What's the reason of this restriction?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The reason for this is that a canonical key must be independent of the phase - thus we pick a constant phase for canonicalization. And this aligns semantically with the concept that source phases can be used as keys in dynamic import.

@guybedford
Copy link
Copy Markdown
Collaborator Author

Note that this won't be landed on its own - instead it will be landed through #58 as it is effectively built on top of there. This PR is instead informative to understand the approach taken in #58.

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.

3 participants