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

Editorial: mostly stop using strings for special values #2566

Merged
merged 5 commits into from
Nov 5, 2021

Conversation

bakkot
Copy link
Contributor

@bakkot bakkot commented Nov 4, 2021

Replaces/ closes #2155.

There are four special strings used in the import/export machinery, one of which is used in three different ways:

  • "*", used in the [[ImportName]] field of an ExportEntry to mark an export * from 'mod'; this has been renamed to ~all-but-default~
  • "*", used in the [[ImportName]] field of an ExportEntry to mark an export * as foo from 'mod' export; this has been renamed to ~all~
  • "*", used in the [[ImportName]] field of an ImportEntry to mark an import * as foo from 'mod' import; this has been renamed to ~namespace-object~
  • "*namespace*", used in the [[BindingName]] field of a ResolvedBinding to mark a export * as foo from 'mod'; this has been renamed to ~namespace~
  • "ambiguous", used in the return value for ResolveExport when resolving a name exported by multiple export * from 'mod' exports; this has been renamed to ~ambiguous~.
  • "*default*", used for default exports which do not have any other name; this has been left alone, and the note about it expanded.

The goal is to unblock #2154 by ensuring that we never use a special string as a placeholder in a context where that PR would allow arbitrary well-formed strings to appear.

@michaelficarra and I spent a couple hours staring at all of this stuff, most of which was fixing our own confusion about how this worked, to wit:

We originally thought that "*default*" was such a string, but it turns out not to be - it is only used as a name strictly internal to a module, to provide the linkage between the "default" export and the local binding by using the same machinery as named exports.

And internally, for named exports, that linkage uses string names looked up in the actual scope object for the module. So the "*default*" string is used in a context which does actually require a string, and thus can't be trivially replaced by a spec enum. We considered modifying the machinery for default exports to work in a different way, but that seemed like it would be more complexity for little benefit, given that it does not actually conflict with #2154, so we've left it along. I did expand the note about "*default*" to hopefully make this clearer to future readers.

On the other hand, "*" was actually being used in a position which would conflict with #2154, as you can see from the [[ImportName]] column of the import * as ns from "mod"; row in this table. So was "*namespace*", as you can sort of see from step 9/10 of this algorithm. (Edit: actually I guess "*namespace*" was ok, on thinking further - step 9 happens after the public -> local name translation has already occurred.)

So this PR does still block #2154, even though we didn't actually end up needing to deal with "*default*".


Just to summarize the relevant machinery here, mostly for my own benefit:

An import creates an ImportEntry Record whose [[ImportName]] is the exported name and whose [[LocalName]] is strictly internal to the module. [[ImportName]] has/had a special case of "*" which indicated a request for the namespace object rather than any particular name.

An export ... from 'foo' creates an ExportEntry Record whose [[ExportName]] is the name visible to importers of this module and whose [[ImportName]] is the name exported by the upstream module ('foo'), and has/had the same special case for "*".

An export ... without a from creates an ExportEntry Record whose [[ExportName]] is the name visible to importers of this module and whose [[LocalName]] is the name used within this module. [[LocalName]] has a special case of "*default*" for anonymous default exports, which is actually a name used on the module's Environment object alongside other top-level variables.

Resolution hooks up these entries to create a ResolvedBinding Record which holds the original module defining the export, and whose [[BindingName]] is the name within that module's environment. It has/had a special case of "*namespace*" which indicated a request for the namespace object rather than any particular name. The [[BindingName]] is derived from an ExportEntry's [[LocalName]], except when the request is for a namespace object. As such, it can be "*default*", which will get looked up within the module's environment like any other name.

Also, if resolution is ambiguous, the string "ambiguous" is used instead of a ResolvedBinding. It's not used in a position where names occur at all.

So, the [[ImportName]] / [[ExportName]] fields hold the actual linker-exposed names, which are the things relaxed by #2154; the other names are strictly internal to a module. Of the special strings, only "*" was used in the linker-exposed position (in [[ImportName]]) and so only "*" actually needed to change. But we might as well get rid of the others while we're at it.

@michaelficarra michaelficarra requested a review from syg November 4, 2021 02:34
spec.html Outdated
@@ -28366,7 +28367,7 @@ <h1>Static Semantics: ExportEntries</h1>
1. Return a List whose sole element is _entry_.
</emu-alg>
<emu-note>
<p>*"\*default\*"* is used within this specification as a synthetic name for anonymous default export values.</p>
<p>*"\*default\*"* is used within this specification as a synthetic name for anonymous default export values. See <emu-xref href="#note-star-default-star">this note</emu-xref> for more details.</p>
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
<p>*"\*default\*"* is used within this specification as a synthetic name for anonymous default export values. See <emu-xref href="#note-star-default-star">this note</emu-xref> for more details.</p>
<p>*"\*default\*"* is used within this specification as a synthetic name for anonymous default export values. See <emu-xref href="#note-star-default-star"></emu-xref> for more details.</p>

I don't like links that say things like "this" or "here".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That note does not have a name or section number, so there's nothing which would be generated there. We need to put some text there.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe this notea note on BoundNames?

Copy link
Contributor

Choose a reason for hiding this comment

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

I prefer the original text of "this note".

@ljharb
Copy link
Member

ljharb commented Nov 4, 2021

awesome, very happy to see #2155 replaced.

Copy link
Contributor

@syg syg left a comment

Choose a reason for hiding this comment

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

Thanks for writing the explanations, made reviewing this a lot easier.

spec.html Outdated
@@ -27671,13 +27672,13 @@ <h1>
1. For each ExportEntry Record _e_ of _module_.[[StarExportEntries]], do
1. Let _importedModule_ be ? HostResolveImportedModule(_module_, _e_.[[ModuleRequest]]).
1. Let _resolution_ be ? _importedModule_.ResolveExport(_exportName_, _resolveSet_).
1. If _resolution_ is *"ambiguous"*, return *"ambiguous"*.
1. If _resolution_ is ~ambiguous~ return ~ambiguous~.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
1. If _resolution_ is ~ambiguous~ return ~ambiguous~.
1. If _resolution_ is ~ambiguous~, return ~ambiguous~.

spec.html Outdated
@@ -28366,7 +28367,7 @@ <h1>Static Semantics: ExportEntries</h1>
1. Return a List whose sole element is _entry_.
</emu-alg>
<emu-note>
<p>*"\*default\*"* is used within this specification as a synthetic name for anonymous default export values.</p>
<p>*"\*default\*"* is used within this specification as a synthetic name for anonymous default export values. See <emu-xref href="#note-star-default-star">this note</emu-xref> for more details.</p>
Copy link
Contributor

Choose a reason for hiding this comment

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

I prefer the original text of "this note".

@bakkot bakkot added the ready to merge Editors believe this PR needs no further reviews, and is ready to land. label Nov 5, 2021
@bakkot bakkot force-pushed the rm-special-module-strings branch 4 times, most recently from 0899420 to 722165e Compare November 5, 2021 23:19
@ljharb ljharb force-pushed the rm-special-module-strings branch from 722165e to 3da5683 Compare November 5, 2021 23:53
@ljharb ljharb merged commit 3da5683 into main Nov 5, 2021
@ljharb ljharb deleted the rm-special-module-strings branch November 5, 2021 23:58
jugglinmike added a commit to bocoup/proposal-Number.range that referenced this pull request Nov 12, 2021
Using an ECMAScript string value to represent internal state may cause
readers to incorrectly assume that the state is directly observable from
ECMAScript code. Replace with a internal specification value in
accordance with the latest practice in ECMA262 [1].

Modify the values so that they will be distinctive in the context of the
specification in order to facilitate tool-assisted search (e.g. via the
`grep` command-line utility or via "Ctrl+F" in a web browser).

[1] tc39/ecma262#2566
Jack-Works pushed a commit to tc39/proposal-iterator.range that referenced this pull request Nov 13, 2021
Using an ECMAScript string value to represent internal state may cause
readers to incorrectly assume that the state is directly observable from
ECMAScript code. Replace with a internal specification value in
accordance with the latest practice in ECMA262 [1].

Modify the values so that they will be distinctive in the context of the
specification in order to facilitate tool-assisted search (e.g. via the
`grep` command-line utility or via "Ctrl+F" in a web browser).

[1] tc39/ecma262#2566
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
editorial change ready to merge Editors believe this PR needs no further reviews, and is ready to land.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants