|
| 1 | +# WAMR Component Model support |
| 2 | + |
| 3 | +## Introduction |
| 4 | + |
| 5 | +A WebAssembly (Wasm) component is an abstraction layer built over [standard WebAssembly](https://webassembly.github.io/spec/core/index.html) (often called WebAssembly Core). It is designed to enrich the exposed type system and improve interoperability across different programming languages and libraries. More details can be found [here](https://component-model.bytecodealliance.org/). |
| 6 | + |
| 7 | +To distinguish between the two layers, the Component Model specification refers to standard WebAssembly entities by prefixing them with the word "core" (e.g., core modules, core functions, core types). |
| 8 | + |
| 9 | +In short, a Wasm component uses WIT—an [Interface Definition Language](https://en.wikipedia.org/wiki/Interface_description_language) (IDL)—to define its public-facing interfaces. It then bundles one or more Wasm core modules to implement the underlying logic behind those interfaces. |
| 10 | + |
| 11 | +WAMR implements binary parsing for the WebAssembly [Component Model](https://github.com/WebAssembly/component-model) proposal. The parser handles the component binary format as defined in the [Binary.md](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Binary.md) specification, covering all 13 section types with validation and error reporting. |
| 12 | + |
| 13 | +References: |
| 14 | +- [Component Model design repository](https://github.com/WebAssembly/component-model) |
| 15 | +- [Component Model binary format specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Binary.md) |
| 16 | +- [Canonical ABI specification](https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md) |
| 17 | +- [Build WAMR vmcore](./build_wamr.md) for build flag reference |
| 18 | + |
| 19 | +## Build |
| 20 | + |
| 21 | +Enable the feature by setting the CMake flag `WAMR_BUILD_COMPONENT_MODEL` (enabled by default). This defines the C preprocessor macro `WASM_ENABLE_COMPONENT_MODEL=1`. |
| 22 | + |
| 23 | +```cmake |
| 24 | +set (WAMR_BUILD_COMPONENT_MODEL 1) |
| 25 | +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) |
| 26 | +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) |
| 27 | +``` |
| 28 | + |
| 29 | +Or pass it on the cmake command line: |
| 30 | + |
| 31 | +```bash |
| 32 | +cmake -DWAMR_BUILD_COMPONENT_MODEL=1 .. |
| 33 | +``` |
| 34 | + |
| 35 | +## Component vs core module |
| 36 | + |
| 37 | +A component binary shares the same magic number (`\0asm`) as a core WebAssembly module but is distinguished by its header fields: |
| 38 | + |
| 39 | +| | Core module | Component | |
| 40 | +|---------------|---------------|---------------| |
| 41 | +| magic | `\0asm` | `\0asm` | |
| 42 | +| version | `0x0001` | `0x000d` | |
| 43 | +| layer | `0x0000` | `0x0001` | |
| 44 | + |
| 45 | +WAMR uses `wasm_decode_header()` to read the 8-byte header and `is_wasm_component()` to determine whether a binary is a component or a core module. |
| 46 | + |
| 47 | +## Binary parsing overview |
| 48 | + |
| 49 | +The binary parser takes a raw component binary buffer and produces a `WASMComponent` structure that holds the decoded header and an array of parsed sections. The diagram below illustrates the high-level parsing flow: |
| 50 | + |
| 51 | +<center><img src="./pics/binary_parser_hld.png" width="85%" height="85%"></img></center> |
| 52 | + |
| 53 | +The parsing proceeds as follows: |
| 54 | + |
| 55 | +1. **Header decode** -- `wasm_decode_header()` reads the 8-byte header (magic, version, layer) and populates a `WASMHeader` struct. |
| 56 | +2. **Section loop** -- the parser iterates over the binary, reading a 1-byte section ID and a LEB128-encoded payload length for each section. |
| 57 | +3. **Section dispatch** -- based on the section ID, the parser delegates to a dedicated per-section parser. Each parser decodes the section payload into a typed struct, validates its contents (UTF-8 names, index bounds, canonical options), and reports how many bytes were consumed. |
| 58 | +4. **Core module delegation** -- when a Core Module section (0x01) is encountered, the parser delegates to the existing WAMR core module loader (`wasm_runtime_load_ex()`) to parse the embedded module. |
| 59 | +5. **Recursive nesting** -- when a Component section (0x04) is encountered, the parser calls itself recursively with an incremented depth counter. Recursion depth is capped at 100. |
| 60 | +6. **Result** -- on success, the `WASMComponent` struct holds the header and a dynamically-sized array of `WASMComponentSection` entries, each containing the raw payload pointer and a typed union with the parsed result. |
| 61 | + |
| 62 | +### Section types |
| 63 | + |
| 64 | +The component binary format defines 13 section types: |
| 65 | + |
| 66 | +| ID | Section | Spec reference | |
| 67 | +|------|------------------|-----------------------------------| |
| 68 | +| 0x00 | Core Custom | custom section (name + data) | |
| 69 | +| 0x01 | Core Module | embedded core wasm module | |
| 70 | +| 0x02 | Core Instance | core module instantiation | |
| 71 | +| 0x03 | Core Type | core func types, module types | |
| 72 | +| 0x04 | Component | nested component (recursive) | |
| 73 | +| 0x05 | Instance | component instance definitions | |
| 74 | +| 0x06 | Alias | export, core export, outer aliases| |
| 75 | +| 0x07 | Type | component type definitions | |
| 76 | +| 0x08 | Canon | canonical lift/lower/resource ops | |
| 77 | +| 0x09 | Start | component start function | |
| 78 | +| 0x0A | Import | component imports | |
| 79 | +| 0x0B | Export | component exports | |
| 80 | +| 0x0C | Value | value definitions | |
| 81 | + |
| 82 | +### Current limitations |
| 83 | + |
| 84 | +- **Core Type (0x03)**: only `moduletype` is supported; WebAssembly GC types (`rectype`, `subtype`) are rejected. |
| 85 | +- **Canon (0x08)**: `async` and `callback` canonical options are rejected; all other canonical operations are supported. |
| 86 | + |
| 87 | +## Source layout |
| 88 | + |
| 89 | +All component model sources reside in `core/iwasm/common/component-model/`: |
| 90 | + |
| 91 | +``` |
| 92 | +component-model/ |
| 93 | + iwasm_component.cmake # CMake build configuration |
| 94 | + wasm_component.h # type definitions, enums, struct declarations |
| 95 | + wasm_component.c # entry point: section dispatch and free |
| 96 | + wasm_component_helpers.c # shared utilities: LEB128, names, value types |
| 97 | + wasm_component_validate.c # validation: UTF-8, index bounds, canon options |
| 98 | + wasm_component_validate.h # validation declarations |
| 99 | + wasm_component_core_custom_section.c # section 0x00 |
| 100 | + wasm_component_core_module_section.c # section 0x01 |
| 101 | + wasm_component_core_instance_section.c # section 0x02 |
| 102 | + wasm_component_core_type_section.c # section 0x03 |
| 103 | + wasm_component_component_section.c # section 0x04 |
| 104 | + wasm_component_instances_section.c # section 0x05 |
| 105 | + wasm_component_alias_section.c # section 0x06 |
| 106 | + wasm_component_types_section.c # section 0x07 |
| 107 | + wasm_component_canons_section.c # section 0x08 |
| 108 | + wasm_component_start_section.c # section 0x09 |
| 109 | + wasm_component_imports_section.c # section 0x0A |
| 110 | + wasm_component_exports_section.c # section 0x0B |
| 111 | + wasm_component_values_section.c # section 0x0C |
| 112 | + wasm_component_export.c # export runtime helpers |
| 113 | + wasm_component_export.h # export declarations |
| 114 | +``` |
0 commit comments