Skip to content

Re-importing a module with an invalid dependency specifier #11820

@nicolo-ribaudo

Description

@nicolo-ribaudo

What is the issue with the HTML Standard?

Ref web-platform-tests/wpt#55598

Consider this module a.js:

import "unresolvable";

When you do import("./a.js") you will get an error thrown because of the unresolvable dependency. What happens if the you re-import it again?

  • WPT tests that you will get again the same error ("bad module specifier in a dependency" in dynamic-imports-script-error.html should be updated web-platform-tests/wpt#55598). Historically (before the modules refactoring), when parsing a module we'd immediately try to resolve all of its dependency specifiers, and if any of them failed resolving we'd then store that error as the module's parse error.
  • The current spec was changed to do this resolution checking every time ECMA-262 asks to load ./a.js's dependencies, which I didn't realize would be an observable difference. This means that every time we do the dynamic import we will successfully load ./a.js (it does not have a parse error anymore!), we will try to resolve its dependencies, and we will generate a new resolution error.

We can update the spec to match again the old behavior, however I'd like to discuss not doing that and instead updating the tests. I have a couple of examples of why I think this makes sense.

1. import source proposal

https://github.com/tc39/proposal-esm-phase-imports allows to do import source of a JS module. It basically means "load this module, but do not load its dependencies yet".

import source of a module with an unresolvable dependency specifier should not throw an error, until when we actually try to complete its processing. For example, we might want to "send" the module to a different environment with different resolution rules (e.g. a worker with a different import map, once they are a thing)

With dynamic import maps, you could even do something like:

const mod = await import.source("./a.js");
installImportMap(); // Make "unresolvable" resolve to something
await import(mod); // resolve mod's dependencies after installing the import map

This use case could also be solved without re-creating an error every time, and instead storing the resolution error as a "dependencies error" (rather than "parser error") that is only thrown when asking to load a module's dependencies. It would make the new behavior identical to the old one, when using plain import().

2. import re-trying

It seems like there is some recent progress in #6768. If that change ever lands, then it might make sense to allow resolution errors to be re-tried:

await import("./a.js").catch(() => {});
installImportMap(); // Make "unresolvable" resolve to something
await import("./a.js"); // does not throw anymore!

Thoughts?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions