@@ -14,7 +14,7 @@ JavaScript runtimes. For a more user-focussed explanation, take a look at the
14
14
* [ Canonical definitions] ( #canonical-definitions )
15
15
* [ Canonical ABI] ( #canonical-built-ins )
16
16
* [ Canonical built-ins] ( #canonical-built-ins )
17
- * [ Start definitions] ( #start-definitions )
17
+ * [ Start definitions] ( #- start-definitions )
18
18
* [ Import and export definitions] ( #import-and-export-definitions )
19
19
* [ Component invariants] ( #component-invariants )
20
20
* [ JavaScript embedding] ( #JavaScript-embedding )
@@ -23,6 +23,15 @@ JavaScript runtimes. For a more user-focussed explanation, take a look at the
23
23
* [ Examples] ( #examples )
24
24
* [ TODO] ( #TODO )
25
25
26
+ By default, the features described in this explainer (as well as the supporting
27
+ [ Binary.md] ( Binary.md ) , [ WIT.md] ( WIT.md ) and [ CanonicalABI.md] ( CanonicalABI.md ) )
28
+ have been implemented and are included in the [ WASI Preview 2] stability
29
+ milestone. Features that are not part of Preview 2 are demarcated by one of the
30
+ emoji symbols listed below; these emojis will be removed once they are
31
+ implemented, considered stable and included in a future milestone:
32
+ * 🪙: value imports/exports and component-level start function
33
+ * 🪺: nested namespaces and packages in import/export names
34
+
26
35
(Based on the previous [ scoping and layering] proposal to the WebAssembly CG,
27
36
this repo merges and supersedes the [ module-linking] and [ interface-types]
28
37
proposals, pushing some of their original features into the post-MVP [ future
@@ -63,7 +72,7 @@ definition ::= core-prefix(<core:module>)
63
72
| <alias>
64
73
| <type>
65
74
| <canon>
66
- | <start>
75
+ | <start> 🪺
67
76
| <import>
68
77
| <export>
69
78
@@ -197,7 +206,7 @@ instantiatearg ::= (with <string> <sortidx>)
197
206
sortidx ::= (<sort> <u32>)
198
207
sort ::= core <core:sort>
199
208
| func
200
- | value
209
+ | value 🪙
201
210
| type
202
211
| component
203
212
| instance
@@ -221,7 +230,7 @@ future include `data`). Thus, component-level `sort` injects the full set
221
230
of ` core:sort ` , so that they may be referenced (leaving it up to validation
222
231
rules to throw out the core sorts that aren't allowed in various contexts).
223
232
224
- The ` value ` sort refers to a value that is provided and consumed during
233
+ 🪙 The ` value ` sort refers to a value that is provided and consumed during
225
234
instantiation. How this works is described in the
226
235
[ start definitions] ( #start-definitions ) section.
227
236
@@ -489,7 +498,7 @@ defvaltype ::= bool
489
498
| float32 | float64
490
499
| char | string
491
500
| (record (field <label> <valtype>)+)
492
- | (variant (case <id>? <label> <valtype>? (refines <id>)? )+)
501
+ | (variant (case <id>? <label> <valtype>?)+)
493
502
| (list <valtype>)
494
503
| (tuple <valtype>+)
495
504
| (flags <label>+)
@@ -520,7 +529,7 @@ externdesc ::= (<sort> (type <u32>) )
520
529
| <functype>
521
530
| <componenttype>
522
531
| <instancetype>
523
- | (value <valtype>)
532
+ | (value <valtype>) 🪙
524
533
| (type <typebound>)
525
534
typebound ::= (eq <typeidx>)
526
535
| (sub resource)
@@ -574,13 +583,6 @@ through these canonical definitions. The `typeidx` immediate of a handle type
574
583
must refer to a ` resource ` type (described below) that statically classifies
575
584
the particular kinds of resources the handle can point to.
576
585
577
- The [ subtyping] between all these types is described in a separate
578
- [ subtyping explainer] ( Subtyping.md ) . Of note here, though: the optional
579
- ` refines ` field in the ` case ` s of ` variant ` s is exclusively concerned with
580
- subtyping. In particular, a ` variant ` subtype can contain a ` case ` not present
581
- in the supertype if the subtype's ` case ` ` refines ` (directly or transitively)
582
- some ` case ` in the supertype.
583
-
584
586
The sets of values allowed for the remaining * specialized value types* are
585
587
defined by the following mapping:
586
588
```
@@ -649,7 +651,7 @@ references to out-of-line type definitions (via `(type <typeidx>)`) and inline
649
651
type expressions that the text format desugars into out-of-line type
650
652
definitions.
651
653
652
- The ` value ` case of ` externdesc ` describes a runtime value that is imported or
654
+ 🪙 The ` value ` case of ` externdesc ` describes a runtime value that is imported or
653
655
exported at instantiation time as described in the
654
656
[ start definitions] ( #start-definitions ) section below.
655
657
@@ -729,11 +731,7 @@ Like core modules, components have an up-front validation phase in which the
729
731
definitions of a component are checked for basic consistency. Type checking
730
732
is a central part of validation and, e.g., occurs when validating that the
731
733
` with ` arguments of an [ ` instantiate ` ] ( #instance-definitions ) expression are
732
- type-compatible with the ` import ` s of the component being instantiated. To allow
733
- backwards-compatible API evolution, "compatibility" is defined in terms of a
734
- [ subtyping] relation, saying that ` t1 ` is "compatible" with ` t2 ` when a value
735
- of type ` t1 ` is * substitutable* for a value of ` t2 ` without breaking any basic
736
- assumptions the receiver has about ` t2 ` values.
734
+ type-compatible with the ` import ` s of the component being instantiated.
737
735
738
736
To incrementally describe how type-checking works, we'll start by asking how
739
737
* type equality* works for non-resource, non-handle, local type definitions and
@@ -766,28 +764,42 @@ all 5 variations of `$ListListStringX` are considered equal since, after
766
764
decoding, they all have the same AST.
767
765
768
766
Next, the type equality relation on ASTs is relaxed to a more flexible
769
- subtyping relation. This subtyping relation is recursively defined starting
770
- with a set of base-case rules such as:
771
- * ` u8 ` is a subtype of ` u16 `
772
- * ` f32 ` is a subtype of ` f64 `
773
-
774
- and then a set of inductive rules like:
775
- * If ` t1 ` is a subtype of ` t2 ` , ` list t1 ` is a subtype of ` list t2 `
776
- * If ` t1 ` is a subtype of ` t2 ` , ` option t1 ` is a subtype of ` option t2 `
777
-
778
- The full list of rules is in [ ` Subtyping.md ` ] ( Subtyping.md ) . The rules are
779
- defined so that a type-checking implementation can simply recurse on the ASTs
780
- of two types in tandem to determine at each node whether the "left-hand side" is
781
- a subtype of the "right-hand side". For example, the following component is
782
- valid because, using the rules just given, the decoded AST of ` $L1 ` is a
783
- subtype of the decoded AST of ` $L2 ` :
784
- ``` wasm
767
+ [ subtyping] relation. Currently, subtyping is only relaxed for ` instance ` and
768
+ ` component ` types, but may be relaxed for more type constructors in the future
769
+ to better support API Evolution (being careful to understand how subtyping
770
+ manifests itself in the wide variety of source languages so that
771
+ subtype-compatible updates don't inadvertantly break source-level clients).
772
+
773
+ Component and instance subtyping allows a subtype to export more and import
774
+ less than is declared by the supertype, ignoring the exact order of imports and
775
+ exports and considering only names. For example, here, ` $I1 ` is a subtype of
776
+ ` $I2 ` :
777
+ ``` wat
785
778
(component
786
- (import "v1" (value $v1 (list (list u8))))
787
- (component $C
788
- (import "v2" (value $v2 (list (list u16))))
789
- )
790
- (instance $c (instantiate $C (with "v2" (value $v1))))
779
+ (type $I1 (instance
780
+ (export "foo" (func))
781
+ (export "bar" (func))
782
+ (export "baz" (func))
783
+ ))
784
+ (type $I2 (instance
785
+ (export "bar" (func))
786
+ (export "foo" (func))
787
+ ))
788
+ )
789
+ ```
790
+ and ` $C1 ` is a subtype of ` $C2 ` :
791
+ ``` wat
792
+ (component
793
+ (type $C1 (component
794
+ (import "a" (func))
795
+ (export "x" (func))
796
+ (export "y" (func))
797
+ ))
798
+ (type $C2 (component
799
+ (import "a" (func))
800
+ (import "b" (func))
801
+ (export "x" (func))
802
+ ))
791
803
)
792
804
```
793
805
@@ -1239,7 +1251,7 @@ See the [CanonicalABI.md](CanonicalABI.md#canonical-definitions) for detailed
1239
1251
definitions of each of these built-ins and their interactions.
1240
1252
1241
1253
1242
- ### Start Definitions
1254
+ ### 🪙 Start Definitions
1243
1255
1244
1256
Like modules, components can have start functions that are called during
1245
1257
instantiation. Unlike modules, components can call start functions at multiple
@@ -1306,19 +1318,22 @@ exported). The grammar for imports and exports is:
1306
1318
import ::= (import <importname> bind-id(<externdesc>))
1307
1319
export ::= (export <id>? <exportname> <sortidx> <externdesc>?)
1308
1320
exportname ::= <name>
1309
- | (interface "<regid>")
1321
+ | (interface "<iid>")
1322
+ iid ::= <namespace><label><projection><version>?
1323
+ | <namespace>+<label><projection>+<version>? 🪺
1324
+ namespace ::= <label>:
1325
+ projection ::= /<label>
1326
+ version ::= @<valid semver>
1310
1327
importname ::= <exportname>
1311
1328
| <name> (url <string> <integrity>?)
1312
1329
| <name> (relative-url <string> <integrity>?)
1313
1330
| <name> <integrity>
1314
- | (locked-dep "<regid>" <integrity>?)
1315
- | (unlocked-dep "<regidset>")
1316
- regname ::= <namespace>+<label><projection>*
1317
- namespace ::= <label>:
1318
- projection ::= /<label>
1319
- regid ::= <regname><version>?
1320
- regidset ::= <regname><verrange>?
1321
- version ::= @<valid semver>
1331
+ | (locked-dep "<pkgid>" <integrity>?)
1332
+ | (unlocked-dep "<pkgidset>")
1333
+ pkgname ::= <namespace><label>
1334
+ | <namespace>+<label><projection>* 🪺
1335
+ pkgid ::= <pkgname><version>?
1336
+ pkgidset ::= <pkgname><verrange>?
1322
1337
verrange ::= <version>
1323
1338
| @*
1324
1339
| @{<verlower>}
@@ -1385,11 +1400,12 @@ host must locate the contents using the hash (e.g., using an [OCI Registry]).
1385
1400
1386
1401
The "registry" referred to by dependency names serves to map a hierarchical
1387
1402
name and version to either a component or an export of a component. For
1388
- example, in the registry name ` a:b:c/d/e/f ` , ` a:b:c ` traverses a path
1389
- through namespaces ` a ` and ` b ` to a component ` c ` and ` /d/e/f ` traverses the
1390
- exports of ` c ` (where ` d ` and ` e ` must be component exports but ` f ` can be
1391
- anything). Given this abstract definition, a number of concrete data sources
1392
- can be interpreted by developer tooling as "registries":
1403
+ example, in the full generality of nested namespaces and packages (🪺),
1404
+ in a registry name ` a:b:c/d/e/f ` , ` a:b:c ` traverses a path through namespaces
1405
+ ` a ` and ` b ` to a component ` c ` and ` /d/e/f ` traverses the exports of ` c ` (where
1406
+ ` d ` and ` e ` must be component exports but ` f ` can be anything). Given this
1407
+ abstract definition, a number of concrete data sources can be interpreted by
1408
+ developer tooling as "registries":
1393
1409
* a live registry (perhaps accessed via [ ` warg ` ] )
1394
1410
* a local filesystem directory (perhaps containing vendored dependencies)
1395
1411
* a fixed set of host-provided functionality (see also the [ built-in modules] proposal)
@@ -1415,8 +1431,8 @@ sequence of labels in a registry name can be translated to nested scopes in the
1415
1431
source language, thereby leveraging existing namespacing in the registry to
1416
1432
avoid conflicts in the source bindings. Note that, because of the mandatory ` : `
1417
1433
in registry names, the set of kebab names and registry names is disjoint and so
1418
- no discriminant is required to distinguish between a ` name ` and ` regname ` ; a
1419
- plain ` string ` covers both cases.
1434
+ no discriminant is required to distinguish between a ` name ` , ` iid ` or ` pkgid ` ;
1435
+ a plain ` string ` covers both cases.
1420
1436
1421
1437
Components provide two options for naming exports, symmetric to the first two
1422
1438
options for naming imports:
@@ -1609,7 +1625,7 @@ For example, the following component:
1609
1625
;; a.wasm
1610
1626
(component
1611
1627
(import "one" (func))
1612
- (import "two" (value string))
1628
+ (import "two" (value string)) 🪙
1613
1629
(import "three" (instance
1614
1630
(export "four" (instance
1615
1631
(export "five" (core module
@@ -1634,7 +1650,7 @@ could be successfully instantiated via:
1634
1650
``` js
1635
1651
WebAssembly .instantiateStreaming (fetch (' ./a.wasm' ), {
1636
1652
one : () => (),
1637
- two: " hi" ,
1653
+ two: " hi" , 🪙
1638
1654
three: {
1639
1655
four: {
1640
1656
five: await WebAssembly .compileStreaming (fetch (' ./b.wasm' ))
@@ -1878,6 +1894,7 @@ and will be added over the coming months to complete the MVP proposal:
1878
1894
[ stack-switching ] : https://github.com/WebAssembly/stack-switching/blob/main/proposals/stack-switching/Overview.md
1879
1895
[ esm-integration ] : https://github.com/WebAssembly/esm-integration/tree/main/proposals/esm-integration
1880
1896
[ gc ] : https://github.com/WebAssembly/gc/blob/main/proposals/gc/MVP.md
1897
+ [ WASI Preview 2 ] : https://github.com/WebAssembly/WASI/tree/main/preview2
1881
1898
1882
1899
[ Adapter Functions ] : FutureFeatures.md#custom-abis-via-adapter-functions
1883
1900
[ Canonical ABI ] : CanonicalABI.md
0 commit comments