Skip to content

Implement canonical interface names in wit-component - #2622

Open
chenyan2002 wants to merge 19 commits into
bytecodealliance:mainfrom
chenyan2002:canon-ver-3
Open

Implement canonical interface names in wit-component#2622
chenyan2002 wants to merge 19 commits into
bytecodealliance:mainfrom
chenyan2002:canon-ver-3

Conversation

@chenyan2002

@chenyan2002 chenyan2002 commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #2556 and replaces #2602.

  • Add config flag emit_canonical_names in ComponentEncoder to emit canonical version.
  • When both implement and versionsuffix are present, the versionsuffix should refer to the version from implement, instead of the main package name.
  • Fixed a bug in merge_world_imports_based_on_semver that implements version is not updated during the merge.
  • Add CLI flag --emit-canonical-names to wasm-tools component new

During the transition period, upstream libraries, e.g., wac, can decode the original binary and re-encode with the emit_canonical_names flag enabled, so that we convert all binaries into their canonical encoding as a preprocessing step. Then wac can merge the interface via string matching directly.

@chenyan2002
chenyan2002 requested a review from a team as a code owner August 25, 2026 00:26
@chenyan2002
chenyan2002 requested review from dicej and removed request for a team August 25, 2026 00:26
Comment thread crates/wit-component/src/encoding/wit.rs Outdated
Comment thread src/bin/wasm-tools/component.rs Outdated
Comment thread src/bin/wasm-tools/component.rs Outdated
Comment thread crates/wit-parser/src/lib.rs Outdated
Comment thread crates/wit-parser/src/resolve/mod.rs Outdated
Comment thread crates/wit-component/src/encoding.rs Outdated
lukewagner pushed a commit to WebAssembly/component-model that referenced this pull request Aug 31, 2026
Tweak the string-splitting to more closely match the intent of versions
found in tooling, specifically:

* Document that build metadata (`+foo` in `0.0.1+foo`) is always split
  out and not part of the canonical name.
* Don't split out pre-release information since pre-release versions are
  incompatible with all other versions.

This additionally matches preexisting merging behavior in
`wit-component` as discovered in bytecodealliance/wasm-tools#2622
Comment thread crates/wasmparser/src/validator/component.rs Outdated
Comment thread crates/wit-component/src/encoding/wit.rs Outdated

fn encode_interface_export(
&mut self,
export_name: &str,

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.

Right now this name logic is now split between the caller and the end of this function, but perhaps this parameter could be changed to ComponentExternName directly to avoid this duplication and instead have the logic in just one place?

external_id: resolve.external_id_value(key, item).map(|s| s.into()),
version_suffix: None,
let implements = resolve.implements_interface(key, item);
if canonical_names {

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.

In a previous review I was curiuos if it would be possible to deduplicate the number of places that a canonical-names option was taken into account and a ComponentExternName were created. I count currently four different locations doing very similar things:

  1. here
  2. below in this file in for interface in interfaces
  3. in encode_interface_import in encoding.rs
  4. in encode_interface_export in encoding.rs (split across two functions)

Were you able to take a look and see if these locations could be unified? Is there perhaps one, or maybe two at most, helpers that could be used to construct these names?

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.

Will think about it tomorrow.

Comment thread crates/wit-component/tests/components/canonical-names/module.wat
Comment thread crates/wit-parser/src/resolve/mod.rs
Comment thread crates/wit-parser/src/resolve/mod.rs
@alexcrichton
alexcrichton removed the request for review from dicej September 5, 2026 04:13

@alexcrichton alexcrichton left a comment

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.

Were there more changes you wanted to make as well? I think the main previously-mentioned-and-possibly-outstanding comment of mine is refactoring the construction fo ComponentExternName, but if you'd prefer that can be deferred to a future change too.

Otherwise though in reading over the tests again I'm thinking that the component model should probably disallow an empty versionsuffix field, which would then require some changes here too. Other than that though I think this is reasonable to land.

Thanks again for working on this!

Comment on lines +4708 to +4711
Some(implements)
} else {
None
};

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.

I think these changes may no longer be necessary

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.

FWIW the changes here seem fine, but for future PRs I the test here don't really have much to do with the feature being added here so I think it'd be fine to just hardcode this to either false or true

)
)
(import "wasi:io/poll@0.2.0-rc-2023-11-10" (instance (;0;) (type 0)))
(import "wasi:io/poll@0.2.0-rc-2023-11-10" (versionsuffix "") (instance (;0;) (type 0)))

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.

I think we'll probably want to handle this differently with a few layers:

  • In the abstract this is a wast of binary-encoding space so we wouldn't want to emit the versionsuffix
  • Additionally though the component model should probably add a validation rule that the length of versionsuffix is >0 since there's not much point in having a 0-length version suffix

Would you be up for adding the new validation rule, adding tests for that, and then adjusting the encoder to skip the suffix if it's empty?

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.

2 participants