This document defines the binary format for the AST defined in the
explainer. The top-level production is component and the
convention is that a file suffixed in .wasm may contain either a
core:module or a component, using the layer field to discriminate
between the two in the first 8 bytes (see below for
more details).
Note: this document is not meant to completely define the decoding or validation rules, but rather merge the minimal need-to-know elements of both, with just enough detail to create a prototype. A complete definition of the binary format and validation will be present in the formal specification.
See Gated Features for an explanation of emoji annotations like 🪙 and 🔧.
(See Component Definitions in the explainer.)
component ::= <preamble> s*:<section>* => (component flatten(s*))
preamble ::= <magic> <version> <layer>
magic ::= 0x00 0x61 0x73 0x6D
version ::= 0x0d 0x00
layer ::= 0x01 0x00
section ::= section_0(<core:custom>) => ϵ
| m: section_1(<core:module>) => [core-prefix(m)]
| i*:section_2(vec(<core:instance>)) => core-prefix(i)*
| t*:section_3(vec(<core:type>)) => core-prefix(t)*
| c: section_4(<component>) => [c]
| i*:section_5(vec(<instance>)) => i*
| a*:section_6(vec(<alias>)) => a*
| t*:section_7(vec(<type>)) => t*
| c*:section_8(vec(<canon>)) => c*
| s: section_9(<start>) => [s] 🪙
| i*:section_10(vec(<import>)) => i*
| e*:section_11(vec(<export>)) => e*
| v*:section_12(vec(<value>)) => v* 🪙Notes:
- Reused Core binary rules:
core:section,core:custom,core:module - The
core-prefix(t)meta-function inserts acoretoken after the leftmost paren oft(e.g.,core-prefix( (module (func)) )is(core module (func))). - The
versiongiven above is pre-standard. As the proposal changes before final standardization,versionwill be bumped from0x0dupwards to coordinate prototypes. When the standard is finalized,versionwill be changed one last time to0x1. (This mirrors the path taken for the Core WebAssembly 1.0 spec.) - The
layerfield is meant to distinguish modules from components early in the binary format. (Core WebAssembly modules already implicitly have alayerfield of0x0if the existing 4-bytecore:versionfield is reinterpreted as two 2-byte fields. This implies that the Core WebAssembly spec needs to make a backwards-compatible spec change to splitcore:versionand fixlayerto forever be0x0.)
(See Instance Definitions in the explainer.)
core:instance ::= ie:<core:instanceexpr> => (instance ie)
core:instanceexpr ::= 0x00 m:<moduleidx> arg*:vec(<core:instantiatearg>) => (instantiate m arg*)
| 0x01 e*:vec(<core:inlineexport>) => e*
core:instantiatearg ::= n:<core:name> 0x12 i:<instanceidx> => (with n (instance i))
core:sortidx ::= sort:<core:sort> idx:<u32> => (sort idx)
core:sort ::= 0x00 => func
| 0x01 => table
| 0x02 => memory
| 0x03 => global
| 0x04 => tag
| 0x10 => type
| 0x11 => module
| 0x12 => instance
core:inlineexport ::= n:<core:name> si:<core:sortidx> => (export n si)
instance ::= ie:<instanceexpr> => (instance ie)
instanceexpr ::= 0x00 c:<componentidx> arg*:vec(<instantiatearg>) => (instantiate c arg*)
| 0x01 e*:vec(<inlineexport>) => e*
instantiatearg ::= n:<name> si:<sortidx> => (with n si)
name ::= n:<core:name> => n
sortidx ::= sort:<sort> idx:<u32> => (sort idx)
sort ::= 0x00 cs:<core:sort> => core cs
| 0x01 => func
| 0x02 => value 🪙
| 0x03 => type
| 0x04 => component
| 0x05 => instance
inlineexport ::= na:<nameattributes> si:<sortidx> => (export na si)Notes:
- Reused Core binary rules:
core:name, (variable-length encoded)core:u32 - The
core:sortvalues are chosen to match the discriminant opcodes ofcore:externtype. typeis added tocore:sortin anticipation of the type-imports proposal. Until that proposal, core modules won't be able to actually import or export types, however, thetypesort is allowed as part of outer aliases (below).moduleandinstanceare added tocore:sortin anticipation of the module-linking proposal, which would add these types to Core WebAssembly. Until then, they are useful for aliases (below).- Validation of
core:instantiatearginitially only allows theinstancesort, but would be extended to accept other sorts as core wasm is extended. - Validation of
instantiaterequires each<externname>incto match anamein awithargument (using plain string equality) and for the types to match. - When validating
instantiate, after each individual type-import is supplied viawith, the actual type supplied is immediately substituted for all uses of the import, so that subsequent imports and all exports are now specialized to the actual type. - The indices in
sortidxare validated according to theirsort's index spaces, which are built incrementally as each definition is validated.
(See Alias Definitions in the explainer.)
alias ::= s:<sort> 0x00 i:<instanceidx> n:<name> => (alias export i n (s))
| s:<sort> 0x01 i:<core:instanceidx> n:<core:name> => (alias core export i n (s))
| s:<sort> 0x02 ct:<u32> idx:<u32> => (alias outer ct idx (s)) (if s in outeraliassort)Notes:
- Reused Core binary rules: (variable-length encoded)
core:u32 - For (
core)exportaliases,iis validated to refer to a (core) instance in the (core) instance index space that exportsnwith the specifiedsort. - For
outeraliases:ctis validated to be less than or equal to the number of enclosing "scopes" (where a "scope" is one of: acomponentdefinition, acomponenttype, aninstancetype)iis validated to be a valid index in thesindex space of the target scope (counting outward, starting with0referring to the current scope)- if
ctis greater than 0 and crosses a component (as opposed to type) boundary andsistype, the target type may not transitively refer to a resource type.
(See Type Definitions in the explainer.)
core:type ::= dt:<core:deftype> => (type dt)
core:deftype ::= rt:<core:rectype> => rt (WebAssembly 3.0)
| 0x00 0x50 x*:vec(<core:typeidx>) ct:<core:comptype> => sub x* ct (WebAssembly 3.0)
| mt:<core:moduletype> => mt
core:moduletype ::= 0x50 md*:vec(<core:moduledecl>) => (module md*)
core:moduledecl ::= 0x00 i:<core:import> => i
| 0x01 t:<core:type> => t
| 0x02 a:<core:alias> => a
| 0x03 e:<core:exportdecl> => e
core:alias ::= 0x10 0x01 ct:<u32> idx:<u32> => (alias outer ct idx (type))
core:importdecl ::= i:<core:import> => i
core:exportdecl ::= n:<core:name> t:<core:externtype> => (export n t)Notes:
- Reused Core binary rules:
core:import,core:externtype, [core:rectype] - Unfortunately, the
core:deftyperule results in an encoding ambiguity: the0x50opcode is used by bothcore:moduletypeand a non-finalcore:subtype, which can be decoded as a top-level form ofcore:rectype. To resolve this, prior to v1.0 of this specification, we requirecore:subtypeto be prefixed by0x00in this context (i.e., a non-finalsubas a component core type is0x00 0x50; elsewhere,0x50). By the v1.0 release of this specification,core:moduletypewill receive a new, non-overlapping opcode. - Validation of
core:moduledeclrejectscore:moduletypedefinitions andouteraliases ofcore:moduletypedefinitions insidetypedeclarators. Thus, as an invariant, when validating acore:moduletype, the core type index space will not contain any core module types. - As described in the explainer, each module type is validated with an initially-empty type index space.
- In
core:alias, the first0x10is the opcode fortypeincore:sortand0x01is an opcode to distinguishouteraliases from potential futureexportaliases.
type ::= dt:<deftype> => (type dt)
deftype ::= dvt:<defvaltype> => dvt
| ft:<functype> => ft
| ct:<componenttype> => ct
| it:<instancetype> => it
| rt:<resourcetype> => rt
primvaltype ::= 0x7f => bool
| 0x7e => s8
| 0x7d => u8
| 0x7c => s16
| 0x7b => u16
| 0x7a => s32
| 0x79 => u32
| 0x78 => s64
| 0x77 => u64
| 0x76 => f32
| 0x75 => f64
| 0x74 => char
| 0x73 => string
| 0x64 => error-context 📝
defvaltype ::= pvt:<primvaltype> => pvt
| 0x72 lt*:vec(<labelvaltype>) => (record (field lt)*) (if |lt*| > 0)
| 0x71 case*:vec(<case>) => (variant case+) (if |case*| > 0)
| 0x70 t:<valtype> => (list t)
| 0x67 t:<valtype> len:<u32> => (list t len) (if len > 0) 🔧
| 0x6f t*:vec(<valtype>) => (tuple t+) (if |t*| > 0)
| 0x6e l*:vec(<labellit>) => (flags l+) (if 0 < |l*| <= 32)
| 0x6d l*:vec(<labellit>) => (enum l+) (if |l*| > 0)
| 0x6b t:<valtype> => (option t)
| 0x6a t?:<valtype>? u?:<valtype>? => (result t? (error u)?)
| 0x69 i:<typeidx> => (own i)
| 0x68 i:<typeidx> => (borrow i)
| 0x66 t?:<valtype>? => (stream t?) 🔀
| 0x65 t?:<valtype>? => (future t?) 🔀
| 0x63 k:<valtype> v:<valtype> => (map k v) (if k is in <keytype>) 🗺️
labelvaltype ::= l:<labellit> t:<valtype> => l t
case ::= l:<labellit> t?:<valtype>? 0x00 => (case l t?)
labellit ::= len:<u32> l:<label> => "l" (if len = |l|)
<T>? ::= 0x00 =>
| 0x01 t:<T> => t
valtype ::= i:<typeidx> => i
| pvt:<primvaltype> => pvt
resourcetype ::= 0x3f v:<valtype> f?:<core:funcidx>? => (resource (rep v) (dtor f)?)
functype ::= 0x40 ps:<paramlist> rs:<resultlist> => (func ps rs)
| 0x43 ps:<paramlist> rs:<resultlist> => (func async ps rs)
paramlist ::= lt*:vec(<labelvaltype>) => (param lt)*
resultlist ::= 0x00 t:<valtype> => (result t)
| 0x01 0x00 =>
componenttype ::= 0x41 cd*:vec(<componentdecl>) => (component cd*)
instancetype ::= 0x42 id*:vec(<instancedecl>) => (instance id*)
componentdecl ::= 0x03 id:<importdecl> => id
| id:<instancedecl> => id
instancedecl ::= 0x00 t:<core:type> => t
| 0x01 t:<type> => t
| 0x02 a:<alias> => a
| 0x04 ed:<exportdecl> => ed
importdecl ::= na:<nameattributes> et:<externtype> => (import na et)
exportdecl ::= na:<nameattributes> et:<externtype> => (export na et)
externtype ::= 0x00 0x11 i:<core:typeidx> => (core module (type i))
| 0x01 i:<typeidx> => (func (type i))
| 0x02 b:<valuebound> => (value b) 🪙
| 0x03 b:<typebound> => (type b)
| 0x04 i:<typeidx> => (component (type i))
| 0x05 i:<typeidx> => (instance (type i))
typebound ::= 0x00 i:<typeidx> => (eq i)
| 0x01 => (sub resource)
valuebound ::= 0x00 i:<valueidx> => (eq i) 🪙
| 0x01 t:<valtype> => t 🪙Notes:
- The type opcodes follow the same negative-SLEB128 scheme as Core WebAssembly,
with type opcodes starting at SLEB128(-1) (
0x7f) and going down, reserving the nonnegative SLEB128s for type indices. - Validation of
valtyperequires thetypeidxto refer to adefvaltype. - Validation of
ownandborrowrequires thetypeidxto refer to a resource type. - Validation of
functyperejects any transitive use ofborrowin aresulttype. Similarly, validation of components and component types rejects any transitive use ofborrowin an exported value type. - Validation of
streamandfuturerejects element types that transitively contain aborrow. - Validation of
streamrejects(stream char)as a temporary TODO. - Validation of
resourcetyperequires the destructor (if present) to have type[i32] -> []. - In addition to the validation rules for
aliasdefinitions mentioned above, validation ofaliasdeclarators also requires:exportaliases only alias theinstanceandtypesortsouteraliases only alias thecore typeandtypesorts
- As described in the explainer, each component and instance type is validated
with an initially-empty type index space. (Outer aliases can be used to pull
in type definitions from containing
componentandtypescopes.) exportdeclintroduces a new type index that can be used by subsequent type definitions. In the(eq i)case, the new type index is effectively an alias to typei. In the(sub resource)case, the new type index refers to a fresh abstract type unequal to every existing type in all existing type index spaces. (Note: subsequent aliases can introduce new type indices equivalent to this fresh type.)- Validation rejects
resourcetypetype definitions insidecomponenttypeandinstancetype. Thus, handle types inside acomponenttypecan only refer to resource types that are imported or exported. <label>is defined as part of the text format.- All parameter labels, result labels, record field labels, variant case labels, flag labels, enum case labels, component import names, component export names, instance import names and instance export names must be strongly-unique in their containing scope.
- Validation of
externtyperequires the varioustypeidxtype constructors to match the precedingsort. - (The
0x00immediate ofcasemay be reinterpreted in the future as thenonecase of an optional immediate.) - 🔧 for fixed-sized lists the length of the list must be larger than 0 to pass validation.
(See Canonical Definitions in the explainer.)
canon ::= 0x00 0x00 f:<core:funcidx> opts:<opts> ft:<typeidx> => (canon lift f opts type-index-space[ft])
| 0x01 0x00 f:<funcidx> opts:<opts> => (canon lower f opts (core func))
| 0x02 rt:<typeidx> => (canon resource.new rt (core func))
| 0x03 rt:<typeidx> => (canon resource.drop rt (core func))
| 0x04 rt:<typeidx> => (canon resource.rep rt (core func))
| 0x08 => (canon backpressure.set (core func)) 🔀✕
| 0x24 => (canon backpressure.inc (core func)) 🔀
| 0x25 => (canon backpressure.dec (core func)) 🔀
| 0x09 rs:<resultlist> opts:<opts> => (canon task.return rs opts (core func)) 🔀
| 0x05 => (canon task.cancel (core func)) 🔀
| 0x0a v:<valtype> i:<u32> => (canon context.get v i (core func)) 🔀
| 0x0b v:<valtype> i:<u32> => (canon context.set v i (core func)) 🔀
| 0x06 async?:<async?> => (canon subtask.cancel async? (core func)) 🔀
| 0x0d => (canon subtask.drop (core func)) 🔀
| 0x0e t:<typeidx> => (canon stream.new t (core func)) 🔀
| 0x0f t:<typeidx> opts:<opts> => (canon stream.read t opts (core func)) 🔀
| 0x10 t:<typeidx> opts:<opts> => (canon stream.write t opts (core func)) 🔀
| 0x11 t:<typeidx> async?:<async?> => (canon stream.cancel-read t async? (core func)) 🔀
| 0x12 t:<typeidx> async?:<async?> => (canon stream.cancel-write t async? (core func)) 🔀
| 0x13 t:<typeidx> => (canon stream.drop-readable t (core func)) 🔀
| 0x14 t:<typeidx> => (canon stream.drop-writable t (core func)) 🔀
| 0x15 t:<typeidx> => (canon future.new t (core func)) 🔀
| 0x16 t:<typeidx> opts:<opts> => (canon future.read t opts (core func)) 🔀
| 0x17 t:<typeidx> opts:<opts> => (canon future.write t opts (core func)) 🔀
| 0x18 t:<typeidx> async?:<async?> => (canon future.cancel-read t async? (core func)) 🔀
| 0x19 t:<typeidx> async?:<async?> => (canon future.cancel-write t async? (core func)) 🔀
| 0x1a t:<typeidx> => (canon future.drop-readable t (core func)) 🔀
| 0x1b t:<typeidx> => (canon future.drop-writable t (core func)) 🔀
| 0x1c opts:<opts> => (canon error-context.new opts (core func)) 📝
| 0x1d opts:<opts> => (canon error-context.debug-message opts (core func)) 📝
| 0x1e => (canon error-context.drop (core func)) 📝
| 0x1f => (canon waitable-set.new (core func)) 🔀
| 0x20 cancel?:<cancel?> m:<core:memidx> => (canon waitable-set.wait cancel? (memory m) (core func)) 🔀
| 0x21 cancel?:<cancel?> m:<core:memidx> => (canon waitable-set.poll cancel? (memory m) (core func)) 🔀
| 0x22 => (canon waitable-set.drop (core func)) 🔀
| 0x23 => (canon waitable.join (core func)) 🔀
| 0x26 => (canon thread.index (core func)) 🧵
| 0x27 ft:<typeidx> tbl:<core:tableidx> => (canon thread.new-indirect ft tbl (core func)) 🧵
| 0x28 => (canon thread.resume-later (core func)) 🧵
| 0x29 cancel?:<cancel?> => (canon thread.suspend cancel? (core func)) 🧵
| 0x0c cancel?:<cancel?> => (canon thread.yield cancel? (core func)) 🔀
| 0x2a cancel?:<cancel?> => (canon thread.suspend-then-resume cancel? (core func)) 🧵
| 0x2b cancel?:<cancel?> => (canon thread.yield-then-resume cancel? (core func)) 🧵
| 0x2c cancel?:<cancel?> => (canon thread.suspend-then-promote cancel? (core func)) 🧵
| 0x2d cancel?:<cancel?> => (canon thread.yield-then-promote cancel? (core func)) 🧵
| 0x40 shared?:<sh?> ft:<typeidx> => (canon thread.spawn-ref shared? ft (core func)) 🧵②
| 0x41 shared?:<sh?> ft:<typeidx> tbl:<core:tableidx> => (canon thread.spawn-indirect shared? ft tbl (core func)) 🧵②
| 0x42 shared?:<sh?> => (canon thread.available-parallelism shared? (core func)) 🧵②
async? ::= 0x00 =>
| 0x01 => async
cancel? ::= 0x00 =>
| 0x01 => cancellable
sh? ::= 0x00 =>
| 0x01 => shared 🧵②
opts ::= opt*:vec(<canonopt>) => opt*
canonopt ::= 0x00 => string-encoding=utf8
| 0x01 => string-encoding=utf16
| 0x02 => string-encoding=latin1+utf16
| 0x03 m:<core:memidx> => (memory m)
| 0x04 f:<core:funcidx> => (realloc f)
| 0x05 f:<core:funcidx> => (post-return f)
| 0x06 => async 🔀
| 0x07 f:<core:funcidx> => (callback f) 🔀Notes:
- The second
0x00byte incanonstands for thefuncsort and thus the0x00 <u32>pair standards for afuncsortidxorcore:sortidx. - Validation prevents duplicate or conflicting
canonopt. - When there is no
string-encodingpresent, the default value isutf8. For all other values, the default value is "none". - Validation of the individual canonical definitions is described in
CanonicalABI.md.
(See Start Definitions in the explainer.)
start ::= f:<funcidx> arg*:vec(<valueidx>) r:<u32> => (start f (value arg)* (result (value))ʳ)Notes:
- Validation requires
fhavefunctypewithparamarity and types matchingarg*andresultarityr. - Validation appends the
resulttypes offto the value index space (making them available for reference by subsequent definitions).
In addition to the type-compatibility checks mentioned above, the validation
rules for value definitions additionally require that each value is consumed
exactly once. Thus, during validation, each value has an associated "consumed"
boolean flag. When a value is first added to the value index space (via
import, instance, alias or start), the flag is clear. When a value is
used (via export, instantiate or start), the flag is set. After
validating the last definition of a component, validation requires all values'
flags are set.
(See Import and Export Definitions in the explainer.)
import ::= na:<nameattributes> et:<externtype> => (import na et)
export ::= na:<nameattributes> si:<sortidx> et?:<externtype>? => (export na si et?)
nameattributes ::= 0x00 len:<u32> en:<externname> => "en" (if len = |en|)
| 0x01 len:<u32> en:<externname> => "en" (if len = |en|)
| 0x02 len:<u32> en:<externname> a*:vec(<attribute>) => "en" a* (if len = |en|) 🏷️/🔗
attribute ::= 0x00 len:<u32> in:<interfacename> => (implements "in") (if len = |in|) 🏷️
| 0x01 len:<u32> vs:<semversuffix> => (versionsuffix "vs") (if len = |vs|) 🔗
| 0x02 n:<name> => (external-id n) 🏷️Notes:
- All exports (of all
sorts) introduce a new index that aliases the exported definition and can be used by all subsequent definitions just like an alias. - Validation requires that all resource types transitively used in the type of an
export are introduced by a preceding
importdeclorexportdecl. - Validation requires any exported
sortidxto have a validexterntype(which disallows core sorts other thancore module). When the optionalexterntypeimmediate is present, validation requires it to be a supertype of the inferredexterntypeof thesortidx. <externname>,<interfacename>and<semversuffix>are defined as part of the text format.- The redundant
0x00/0x01cases ofnameattributeswill be cleaned up for a 1.0 release. - The
externnames of all imports in a given component or component-type must be strongly-unique; attributes are ignored. - The
externnames of all exports in a given component, instance, component- type or instance-type must be strongly-unique; attributes are ignored. - Validation requires that
[constructor],[method]and[static]annotatedplainnames only occur onfuncimports or exports and that the first label of a[constructor],[method]or[static]matches theplainnameof a precedingresourceimport or export, respectively, in the same scope (component, component type or instance type). - 🏷️ Validation requires that
implements-annotated imports or exports areinstance-typed and have aplainnamename. - 🏷️/🔗 Validation requires that a
vec(<attribute>)contains each kind ofattributeat most once. - 🏷️/🔗 Even though
componenttypeandinstancetypestructurally contain avec(<attribute>), this list is entirely ignored when validating the types of components and instances. - Validation of
[constructor]names requires afunctype whose result type is either(own $R)or(result (own $R) E?)where$Ris a resource type labeledr. - Validation of
[method]names requires the first parameter of the function to be(param "self" (borrow $R)), where$Ris the resource labeledr. - 🔗 Validation requires that
versionsuffixis preceded by aninterfaceversionmatchingcanonversionand that the concatenation of thecanonversionand theversionsuffixresults in avalid semveras defined by https://semver.org. Aversionsuffixis otherwise ignored for validation except to improve diagnostic messages.
(See Value Definitions in the explainer.)
value ::= t:<valtype> len:<core:u32> v:<val(t)> => (value t v) (where len = ||v||)
val(bool) ::= 0x00 => false
| 0x01 => true
val(u8) ::= v:<core:byte> => v
val(s8) ::= v:<core:byte> => v' (where v' = v if v < 128 else (v - 256))
val(s16) ::= v:<core:s16> => v
val(u16) ::= v:<core:u16> => v
val(s32) ::= v:<core:s32> => v
val(u32) ::= v:<core:u32> => v
val(s64) ::= v:<core:s64> => v
val(u64) ::= v:<core:u64> => v
val(f32) ::= v:<core:f32> => v (if !isnan(v))
| 0x00 0x00 0xC0 0x7F => nan
val(f64) ::= v:<core:f64> => v (if !isnan(v))
| 0x00 0x00 0x00 0x00 0x00 0x00 0xF8 0x7F => nan
val(char) ::= b*:<core:byte>* => c (where b* = core:utf8(c))
val(string) ::= v:<core:name> => v
val(i:<typeidx>) ::= v:<val(type-index-space[i])> => v
val((record (field l t)+)) ::= v+:<val(t)>+ => (record v+)
val((variant (case l t?)+) ::= i:<core:u32> v?:<val(t[i])>? => (variant l[i] v?)
val((list t)) ::= v:vec(<val(t)>) => (list v)
val((tuple t+)) ::= v+:<val(t)>+ => (tuple v+)
val((flags l+)) ::= (v:<core:byte>)^N => (flags (l[i] for i in 0..|l+|-1 if v[floor(i / 8)] & 2^(i mod 8) > 0)) (where N = ceil(|l+| / 8))
val((enum l+)) ::= i:<core:u32> => (enum l[i])
val((option t)) ::= 0x00 => none
| 0x01 v:<val(t)> => (some v)
val((result)) ::= 0x00 => ok
| 0x01 => error
val((result t)) ::= 0x00 v:<val(t)> => (ok v)
| 0x01 => error
val((result (error u))) ::= 0x00 => ok
| 0x01 v:<val(u)> => (error v)
val((result t (error u))) ::= 0x00 v:<val(t)> => (ok v)
| 0x01 v:<val(u)> => (error v)Notes:
- Reused Core binary rules and functions:
&operator is used to denote bitwise AND operation, which performs AND on every bit of two numbers in their binary formisnanis a function, which takes a floating point number as a parameter and returnstrueiff it represents a NaN as defined in IEEE 754 standard||B||is the length of the byte sequence generated from the productionBin a derivation as defined in Core convention auxiliary notation
Like the core wasm name
section
a similar name custom section is specified here for components to be able to
name all the declarations that can happen within a component. Similarly like its
core wasm counterpart validity of this custom section is not required and
engines should not reject components which have an invalid name section.
namesec ::= section_0(namedata)
namedata ::= n:<name> (if n = 'component-name')
name:<componentnamesubsec>?
sortnames*:<sortnamesubsec>*
namesubsection_N(B) ::= N:<byte> size:<u32> B (if size == |B|)
componentnamesubsec ::= namesubsection_0(<name>)
sortnamesubsec ::= namesubsection_1(<sortnames>)
sortnames ::= sort:<sort> names:<namemap>
namemap ::= names:vec(<nameassoc>)
nameassoc ::= idx:<u32> name:<name>where namemap is the same as for core wasm. A particular sort should only
appear once within a name section, for example component instances can only be
named once.
- The opcodes (for types, canon built-ins, etc) should be re-sorted
- The two
listtype codes should be merged into one with an optional immediate and similarly forfunc. - The redundant
0x00and0x01opcodes ofnameattributeswill be merged. - Most built-ins should have a
<canonopt>*immediate instead of an ad hoc subset ofcanonopts. - Add optional
sharedimmediate to all canonical definitions (explicitly or via<canonopt>) when shared-everything-threads (🧵②) is added.