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

Invalid attributes keys in static imports should be a resolution/loading error and not a parsing error #144

Closed
nicolo-ribaudo opened this issue Jun 22, 2023 · 5 comments · Fixed by whatwg/html#9599

Comments

@nicolo-ribaudo
Copy link
Member

import "x" with { unknownAttr: "y" }

Should parse successfully, and fail trying to load the imported module.

This is not currently observable within ECMA-262, but it affects how errors are reported for code that contains an actual syntax error:

import "x" with { unknownAttr: "y" }

a b c

Reporting the parsing error at the attribute rather than at the missing semicolon after a is very awkward.

@nicolo-ribaudo
Copy link
Member Author

This has been fixed.

@nicolo-ribaudo
Copy link
Member Author

nicolo-ribaudo commented Aug 1, 2023

I'm reopening this because I noticed that this change caused an assertion in HTML to be invalid (step 9 of https://html.spec.whatwg.org/#creating-a-javascript-module-script).

Right now, ignoring that assertion, when loading a module this is what happens:

  1. (HTML) Fetch the module source code (this might throw)
  2. (ECMA-262) Parse the module (this might throw)
  3. (HTML) For each import of the module,
    1. (HTML) Resolve the URL (this might throw) — step 10.1 of https://html.spec.whatwg.org/#creating-a-javascript-module-script
    2. (HTML) Check that it has a valid type attribute, if any (this might throw)
  4. (ECMA-262) For each imported module,
    1. (ECMA-262) Check that it does not have any unknown attribute (this might throw)
    2. (HTML) Resolve the URL — step 8 of https://html.spec.whatwg.org/#hostloadimportedmodule
    3. Re-run all these steps for the new module

We have two options:

  1. Duplicate step 4.1 in 3, similarly to how 4.2 is already duplicated to report resolution errors early
  2. Just remove the assertion, which doesn't add any value to the "create a JavaScript module script" algorithm. Note that the assertion in https://html.spec.whatwg.org/#fetch-a-single-imported-module-script would still hold, because it happens in 4.3.

I'm implementing this in chromium, and the complexity of doing 1 vs 2 is the same. I have a slight preference for duplicating the check, to align it with modules URL resolution. For dynamic import, currently the check for invalid attribute keys happens before trying to resolve the URL (because it happens in ECMA-262 before calling in HTML).

cc @domenic

@nicolo-ribaudo
Copy link
Member Author

Doing (2) also has the benefit of aligning static and dynamic imports.

Given this code:

await Promise.all([
    import("https://example.com/x", { with: { type: "foo" } }).catch(e => e.message),
    import("x", { with: { type: "foo" } }).catch(e => e.message),
    import("https://example.com/x", { with: { invalid: "foo" } }).catch(e => e.message),
    import("x", { with: { invalid: "foo" } }).catch(e => e.message),
    import('data:text/javascript, import "https://example.com/x" with { type: "foo" }').catch(e => e.message),
    import('data:text/javascript, import "x" with { type: "foo" }').catch(e => e.message),
    import('data:text/javascript, import "https://example.com/x" with { invalid: "foo" }').catch(e => e.message),
    import('data:text/javascript, import "x" with { invalid: "foo" }').catch(e => e.message),
]);

with (1) it would print

[
  "\"foo\" is not a valid module type.",
  "Failed to resolve module specifier 'x'",
  "Invalid attribute key \"invalid\".",
  "Invalid attribute key \"invalid\".",
  "\"foo\" is not a valid module type.",
  "Failed to resolve module specifier \"x\".",
  "Invalid attribute key \"invalid\".",
  "Failed to resolve module specifier \"x\".",
]

while with (2) it would print

[
  "\"foo\" is not a valid module type.",
  "Failed to resolve module specifier 'x'",
  "Invalid attribute key \"invalid\".",
  "Invalid attribute key \"invalid\".",
  "\"foo\" is not a valid module type.",
  "Failed to resolve module specifier \"x\".",
  "Invalid attribute key \"invalid\".",
  "Invalid attribute key \"invalid\"."
]

@domenic
Copy link
Member

domenic commented Aug 2, 2023

I don't think I have strong feelings here but all else being equal, aligning dynamic and static imports seems nice.

The assert in step 9 does seem pretty inconsequential to me so removing it from HTML doesn't seem like a big deal.

domenic pushed a commit to whatwg/html that referenced this issue Aug 23, 2023
When creating a module script, there is no guarantee yet that the module's dependencies only have valid import attribute keys. Instead of asserting that only type is used, this commit introduces proper validation throwing a SyntaxError.

This is done in a way that aligns error cases for static imports with dynamic import()s, and error causes caught in HTML with those caught in ECMA-262.

Closes tc39/proposal-import-attributes#144.
@nicolo-ribaudo
Copy link
Member Author

Fixed in whatwg/html#9599

rubberyuzu pushed a commit to rubberyuzu/html that referenced this issue Aug 25, 2023
When creating a module script, there is no guarantee yet that the module's dependencies only have valid import attribute keys. Instead of asserting that only type is used, this commit introduces proper validation throwing a SyntaxError.

This is done in a way that aligns error cases for static imports with dynamic import()s, and error causes caught in HTML with those caught in ECMA-262.

Closes tc39/proposal-import-attributes#144.
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 a pull request may close this issue.

2 participants