Skip to content

Implement Import Attributes proposal#4549

Merged
nekevss merged 44 commits intoboa-dev:mainfrom
rrogerc:main
Dec 4, 2025
Merged

Implement Import Attributes proposal#4549
nekevss merged 44 commits intoboa-dev:mainfrom
rrogerc:main

Conversation

@rrogerc
Copy link
Copy Markdown
Contributor

@rrogerc rrogerc commented Nov 27, 2025

This Pull Request closes #4440, implementing the Import Attributes proposal

It changes the following:

  • Implemented the with clause (and assert fallback) for imports, re-exports, and dynamic imports.
  • Updated ModuleLoader and ModuleRequest to support attributes in module resolution and caching.
  • Added handling for type: "json" in SimpleModuleLoader to verify attribute behavior.

rrogerc and others added 13 commits November 25, 2025 00:55
Introduces the `ImportAttribute` struct, which represents
a single key-value pair in the import attributes syntax:

   import json from "./foo.json" with { type: "json" };

The struct stores both the key and value as `Sym` (interned strings).
Extends `ImportDeclaration` to support import attributes by adding an
`attributes` field that stores a boxed slice of `ImportAttribute`.
Extends the `ReExport` variant of `ExportDeclaration` to support import
attributes for re-export statements like:
    export { val } from './foo.js' with { type: "json" };
    export * from './foo.json' with { type: "json" };
Extends `ImportCall` to support the optional second argument used for
import attributes in dynamic imports:
    import("foo.json", { with: { type: "json" } })
Implements parsing of the `with { ... }` clause used in import attributes:
    import json from "./foo.json" with { type: "json" };
Updates the import declaration parser to parse import attributes using
the `WithClause` parser. Import declarations now support the syntax:
    import json from "./foo.json" with { type: "json" };
    import { val } from "./foo.js" with { type: "json" };
    import * as ns from "./foo.json" with { type: "json" };
Updates the export declaration parser to parse import attributes for
re-export statements using the `WithClause` parser:
    export * from './foo.json' with { type: "json" };
    export * as ns from './foo.json' with { type: "json" };
    export { val } from './foo.js' with { type: "json" };
Updates the dynamic import parser to handle the optional options argument
used for import attributes:
    import("foo.json", { with: { type: "json" } })
* Implement dynamic import attributes support

- Update Opcode::ImportCall to accept options operand.

- Update ByteCompiler to emit ImportCall with options argument.

- Update load_dyn_import to extract import attributes from options object.

- Fix Instruction::ImportCall debug formatting.

- Update ModuleLoader usage in tests.

* Add test case for dynamic import with attributes

* Refactor ModuleRequestsVisitor and fix clippy warnings

* Remove unsafe_ignore_trace from ModuleRequest

* Add test cases for static import and re-export with attributes

* Fix test compilation by removing reference in assertion

* Enforce string type for dynamic import attribute values

- Update load_dyn_import to reject non-string values in import attributes.

- Add test cases for invalid attribute value types.

* cleanup
@github-actions
Copy link
Copy Markdown

github-actions bot commented Nov 27, 2025

Test262 conformance changes

Test result main count PR count difference
Total 50,747 50,747 0
Passed 47,877 47,966 +89
Ignored 2,060 1,971 -89
Failed 810 810 0
Panics 0 0 0
Conformance 94.34% 94.52% +0.18%
Fixed tests (89):
test/language/expressions/dynamic-import/syntax/valid/nested-function-return-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-await-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-if-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-block-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-async-function-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-with-expression-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-if-braceless-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-if-braceless-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-return-await-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-with-expression-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-block-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-else-braceless-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-async-function-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-async-function-await-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-do-while-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-async-function-return-await-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-return-await-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-block-labeled-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-else-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-function-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-while-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-async-gen-await-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-function-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-if-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-async-function-return-await-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-else-braceless-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/top-level-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-async-function-await-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-arrow-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-async-gen-await-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-else-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-do-while-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-while-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-arrow-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-arrow-assignment-expression-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-block-labeled-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-with-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-async-arrow-function-await-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-with-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-function-return-import-attributes-trailing-comma-first.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/nested-arrow-assignment-expression-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/syntax/valid/top-level-import-attributes-trailing-comma-second.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-yield-ident-invalid.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-with-non-object.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-trailing-comma-fulfill.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-with-enumeration.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-evaluation-sequence.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-yield-expr.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-with-undefined.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-in.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-yield-ident-valid.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-trailing-comma-reject.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-with-value-abrupt.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-await-expr.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-evaluation-abrupt-return.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/trailing-comma-fulfill.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-non-object.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-await-ident.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-with-enumeration-enumerable.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-with-value-non-string.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-evaluation-abrupt-throw.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-with-enumeration-abrupt.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/2nd-param-get-with-error.js (previously Ignored)
test/language/expressions/dynamic-import/import-attributes/trailing-comma-reject.js (previously Ignored)
test/language/import/import-attributes/json-value-boolean.js (previously Ignored)
test/language/import/import-attributes/json-value-string.js (previously Ignored)
test/language/import/import-attributes/json-value-null.js (previously Ignored)
test/language/import/import-attributes/json-invalid.js (previously Ignored)
test/language/import/import-attributes/json-value-array.js (previously Ignored)
test/language/import/import-attributes/json-idempotency.js (previously Ignored)
test/language/import/import-attributes/json-value-number.js (previously Ignored)
test/language/import/import-attributes/json-named-bindings.js (previously Ignored)
test/language/import/import-attributes/json-extensibility-array.js (previously Ignored)
test/language/import/import-attributes/json-via-namespace.js (previously Ignored)
test/language/import/import-attributes/json-extensibility-object.js (previously Ignored)
test/language/import/import-attributes/json-value-object.js (previously Ignored)
test/language/module-code/import-attributes/allow-nlt-before-with.js (previously Ignored)
test/language/module-code/import-attributes/early-dup-attribute-key-export.js (previously Ignored)
test/language/module-code/import-attributes/import-attribute-newlines.js (previously Ignored)
test/language/module-code/import-attributes/import-attribute-key-string-double.js (previously Ignored)
test/language/module-code/import-attributes/import-attribute-key-identifiername.js (previously Ignored)
test/language/module-code/import-attributes/import-attribute-key-string-single.js (previously Ignored)
test/language/module-code/import-attributes/early-dup-attribute-key-import-withbinding.js (previously Ignored)
test/language/module-code/import-attributes/import-attribute-value-string-single.js (previously Ignored)
test/language/module-code/import-attributes/import-attribute-many.js (previously Ignored)
test/language/module-code/import-attributes/early-dup-attribute-key-import-nobinding.js (previously Ignored)
test/language/module-code/import-attributes/import-attribute-trlng-comma.js (previously Ignored)
test/language/module-code/import-attributes/import-attribute-empty.js (previously Ignored)
test/language/module-code/import-attributes/import-attribute-value-string-double.js (previously Ignored)

@codecov
Copy link
Copy Markdown

codecov bot commented Nov 27, 2025

Codecov Report

❌ Patch coverage is 72.04301% with 104 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.40%. Comparing base (6ddc2b4) to head (ae5e601).
⚠️ Report is 609 commits behind head on main.

Files with missing lines Patch % Lines
core/engine/src/module/loader/mod.rs 36.53% 33 Missing ⚠️
...ore/parser/src/parser/statement/declaration/mod.rs 69.23% 16 Missing ⚠️
core/engine/src/module/source.rs 72.34% 13 Missing ⚠️
core/engine/src/vm/opcode/call/mod.rs 87.27% 7 Missing ⚠️
core/ast/src/expression/call.rs 71.42% 6 Missing ⚠️
core/engine/src/module/mod.rs 75.00% 6 Missing ⚠️
core/ast/src/declaration/export.rs 80.95% 4 Missing ⚠️
core/ast/src/module_item_list/mod.rs 76.47% 4 Missing ⚠️
...parser/src/parser/expression/left_hand_side/mod.rs 81.25% 3 Missing ⚠️
core/ast/src/scope_analyzer.rs 33.33% 2 Missing ⚠️
... and 6 more
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #4549       +/-   ##
===========================================
+ Coverage   47.24%   57.40%   +10.16%     
===========================================
  Files         476      504       +28     
  Lines       46892    57849    +10957     
===========================================
+ Hits        22154    33209    +11055     
+ Misses      24738    24640       -98     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Member

@nekevss nekevss left a comment

Choose a reason for hiding this comment

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

There's still probably some more to review, but thought I'd leave some early review comments on this.

Overall, great work on this so far! Mostly had just some general nits and questions for now.

matches!(tok.kind(), TokenKind::IdentifierName((sym, _)) if interner.resolve_expect(*sym).utf8().is_some_and(|s| s == "assert"))
};

// Only treat `with` / `assert` as part of a with-clause if it is
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.

question: why is assert still supported?

I only took a quick glance at the specification and it looks like assert was removed from the proposal.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oh, if you look at the bottom of the proposal, under history it says "For compatibility with existing implementations, the assert keyword will still be supported until it's safe to remove it, if it will ever be."

Though let me know if I’ve misunderstood though!

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.

Based off tc39/proposal-import-attributes#135, I would go with we should only support with out of the box.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the link, we've updated it to remove it entirely!

@HalidOdat HalidOdat self-requested a review December 1, 2025 16:12
Copy link
Copy Markdown
Member

@HalidOdat HalidOdat left a comment

Choose a reason for hiding this comment

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

Great work! 😄

Copy link
Copy Markdown
Member

@HalidOdat HalidOdat left a comment

Choose a reason for hiding this comment

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

Awesome work! Looks good to me! 😄

Copy link
Copy Markdown
Member

@nekevss nekevss left a comment

Choose a reason for hiding this comment

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

LGTM!

Thanks for adding all the tests for this as well 😄

@nekevss
Copy link
Copy Markdown
Member

nekevss commented Dec 4, 2025

Thanks for contributing this!!!

@nekevss nekevss added this pull request to the merge queue Dec 4, 2025
@jedel1043 jedel1043 added A-Enhancement New feature or request C-AST Issue surrounding the abstract syntax tree labels Dec 4, 2025
Merged via the queue into boa-dev:main with commit 7df2cdc Dec 4, 2025
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Enhancement New feature or request C-AST Issue surrounding the abstract syntax tree

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement import attributes proposal

6 participants