Skip to content

Commit 9fde369

Browse files
authored
Clarify what's in Preview 2 (#255)
* Clarify what's in Preview 2 Resolves #229 * Split out package and interface id cases in the grammar * Require the 'refines' immediate to be 0
1 parent 01ebd9e commit 9fde369

File tree

5 files changed

+105
-107
lines changed

5 files changed

+105
-107
lines changed

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@ reference interpreter and test suite.
1212

1313
## Milestones
1414

15-
The Component Model is being incrementally developed and stabilized as part of
16-
the overall [WASI preview process]. The current contents of this repo reflect
17-
the "Preview 2" milestone. The "Preview 3" milestone will be primarily
18-
concerned with the addition of [async support].
15+
The Component Model is currently being incrementally developed and stabilized
16+
as part of [WASI Preview 2]. The subsequent "Preview 3" milestone will be
17+
primarily concerned with the addition of [async support].
1918

2019
## Contributing
2120

@@ -35,5 +34,5 @@ To contribute to any of these repositories, see the Community Group's
3534
[formal spec]: spec/
3635
[W3C WebAssembly Community Group]: https://www.w3.org/community/webassembly/
3736
[Contributing Guidelines]: https://webassembly.org/community/contributing/
38-
[WASI preview process]: https://github.com/WebAssembly/meetings/blob/main/wasi/2023/presentations/2023-02-09-gohman-wasi-roadmap.pdf
37+
[WASI Preview 2]: https://github.com/WebAssembly/WASI/tree/main/preview2
3938
[Async Support]: https://docs.google.com/presentation/d/1MNVOZ8hdofO3tI0szg_i-Yoy0N2QPU2C--LzVuoGSlE/edit?usp=share_link

design/mvp/Binary.md

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ rules, but rather merge the minimal need-to-know elements of both, with just
1212
enough detail to create a prototype. A complete definition of the binary format
1313
and validation will be present in the [formal specification](../../spec/).
1414

15+
See the [explainer introduction](Explainer.md) for an explanation of 🪙.
16+
1517

1618
## Component Definitions
1719

@@ -74,7 +76,7 @@ instantiatearg ::= n:<string> si:<sortidx> => (w
7476
sortidx ::= sort:<sort> idx:<u32> => (sort idx)
7577
sort ::= 0x00 cs:<core:sort> => core cs
7678
| 0x01 => func
77-
| 0x02 => value
79+
| 0x02 => value 🪙
7880
| 0x03 => type
7981
| 0x04 => component
8082
| 0x05 => instance
@@ -102,8 +104,8 @@ Notes:
102104
for aliases (below).
103105
* Validation of `core:instantiatearg` initially only allows the `instance`
104106
sort, but would be extended to accept other sorts as core wasm is extended.
105-
* Validation of `instantiate` requires each `<name>`, `<regid>` or
106-
`<regidset>` in an `importname` in `c` to match a `string` in a `with`
107+
* Validation of `instantiate` requires each `<name>`, `<iid>`, `<pkgid>` or
108+
`<pkgidset>` in an `importname` in `c` to match a `string` in a `with`
107109
argument and for the types to match.
108110
* When validating `instantiate`, after each individual type-import is supplied
109111
via `with`, the actual type supplied is immediately substituted for all uses
@@ -207,7 +209,7 @@ defvaltype ::= pvt:<primvaltype> => pvt
207209
| 0x69 i:<typeidx> => (own i)
208210
| 0x68 i:<typeidx> => (borrow i)
209211
labelvaltype ::= l:<label> t:<valtype> => l t
210-
case ::= l:<label> t?:<valtype>? r?:<u32>? => (case l t? (refines case-label[r])?)
212+
case ::= l:<label> t?:<valtype>? 0x00 => (case l t?)
211213
<T>? ::= 0x00 =>
212214
| 0x01 t:<T> => t
213215
valtype ::= i:<typeidx> => i
@@ -229,7 +231,7 @@ importdecl ::= in:<importname> ed:<externdesc> => (import in ed)
229231
exportdecl ::= en:<exportname> ed:<externdesc> => (export en ed)
230232
externdesc ::= 0x00 0x11 i:<core:typeidx> => (core module (type i))
231233
| 0x01 i:<typeidx> => (func (type i))
232-
| 0x02 t:<valtype> => (value t)
234+
| 0x02 t:<valtype> => (value t) 🪙
233235
| 0x03 b:<typebound> => (type b)
234236
| 0x04 i:<typeidx> => (component (type i))
235237
| 0x05 i:<typeidx> => (instance (type i))
@@ -269,9 +271,8 @@ Notes:
269271
* Validation of function parameter and result names, record field names,
270272
variant case names, flag names, and enum case names requires that the name be
271273
unique for the func, record, variant, flags, or enum type definition.
272-
* Validation of the optional `refines` clause of a variant case requires that
273-
the case index is less than the current case's index (and therefore
274-
cases are acyclic).
274+
* (The `0x00` immediate of `case` may be reinterpreted in the future as the
275+
`none` case of an optional immediate.)
275276

276277

277278
## Canonical Definitions
@@ -299,7 +300,7 @@ Notes:
299300
[`CanonicalABI.md`](CanonicalABI.md#canonical-definitions).
300301

301302

302-
## Start Definitions
303+
## 🪙 Start Definitions
303304

304305
(See [Start Definitions](Explainer.md#start-definitions) in the explainer.)
305306
```ebnf
@@ -329,15 +330,16 @@ in the explainer.)
329330
import ::= in:<importname> ed:<externdesc> => (import in ed)
330331
export ::= en:<exportname> si:<sortidx> ed?:<externdesc>? => (export en si ed?)
331332
exportname ::= 0x00 n:<name> => n
332-
| 0x01 ri:<regid'> => (interface ri)
333+
| 0x01 i:<iid'> => (interface i)
334+
iid' ::= len:<u32> i:<iid> => "i" (if len = |i|)
333335
importname ::= en:<exportname> => en
334336
| 0x02 n:<name> s:<string> i?:<integrity'>? => n (url s i?)
335337
| 0x03 n:<name> s:<string> i?:<integrity'>? => n (relative-url s i?)
336338
| 0x04 n:<name> i:<integrity'> => n i
337-
| 0x05 ri:<regid'> i?:<integrity'>? => (locked-dep ri i?)
338-
| 0x06 ris:<regidset'> => (unlocked-dep ris)
339-
regid' ::= len:<u32> ri:<regid> => "ri" (if len = |ri|)
340-
regidset' ::= len:<u32> ris:<regidset> => "ris" (if len = |ris|)
339+
| 0x05 p:<pkgid'> i?:<integrity'>? => (locked-dep p i?)
340+
| 0x06 p:<pkgidset'> => (unlocked-dep p)
341+
pkgid' ::= len:<u32> p:<pkgid> => "p" (if len = |p|)
342+
pkgidset' ::= len:<u32> p:<pkgidset> => "p" (if len = |p|)
341343
integrity' ::= len:<u32> im:<integrity-metadata> => (integrity "im") (if len = |im|)
342344
```
343345

@@ -353,11 +355,10 @@ Notes:
353355
* The `name` fields of `exportname` and `importname` must be unique among all
354356
imports and exports in the containing component definition, component type or
355357
instance type. (An import and export cannot use the same `name`.)
356-
* The `regid` and `regidset` of `importname` and `exportname` must be
358+
* The `iid`, `pkgid` and `pkgidset` of `importname` and `exportname` must be
357359
unique only among imports or exports. That is, two imports may *not*
358-
have the same `regid`(`set`), but an import and export *may* have the same
359-
`regid`.
360-
* `<regid>` and `<regidset>` refer to the grammatical productions defined in
360+
have the same id, but an import and export *may* have the same id.
361+
* `<iid>`, `<pkgid>` and `<pkgidset>` refer to the grammatical productions defined in
361362
the [text format](#import-and-export-definitions).
362363
* `<valid semver>` is as defined by [https://semver.org](https://semver.org/)
363364
* `<integrity-metadata>` is as defined by the

design/mvp/Explainer.md

Lines changed: 76 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ JavaScript runtimes. For a more user-focussed explanation, take a look at the
1414
* [Canonical definitions](#canonical-definitions)
1515
* [Canonical ABI](#canonical-built-ins)
1616
* [Canonical built-ins](#canonical-built-ins)
17-
* [Start definitions](#start-definitions)
17+
* [Start definitions](#-start-definitions)
1818
* [Import and export definitions](#import-and-export-definitions)
1919
* [Component invariants](#component-invariants)
2020
* [JavaScript embedding](#JavaScript-embedding)
@@ -23,6 +23,15 @@ JavaScript runtimes. For a more user-focussed explanation, take a look at the
2323
* [Examples](#examples)
2424
* [TODO](#TODO)
2525

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+
2635
(Based on the previous [scoping and layering] proposal to the WebAssembly CG,
2736
this repo merges and supersedes the [module-linking] and [interface-types]
2837
proposals, pushing some of their original features into the post-MVP [future
@@ -63,7 +72,7 @@ definition ::= core-prefix(<core:module>)
6372
| <alias>
6473
| <type>
6574
| <canon>
66-
| <start>
75+
| <start> 🪺
6776
| <import>
6877
| <export>
6978
@@ -197,7 +206,7 @@ instantiatearg ::= (with <string> <sortidx>)
197206
sortidx ::= (<sort> <u32>)
198207
sort ::= core <core:sort>
199208
| func
200-
| value
209+
| value 🪙
201210
| type
202211
| component
203212
| instance
@@ -221,7 +230,7 @@ future include `data`). Thus, component-level `sort` injects the full set
221230
of `core:sort`, so that they may be referenced (leaving it up to validation
222231
rules to throw out the core sorts that aren't allowed in various contexts).
223232

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
225234
instantiation. How this works is described in the
226235
[start definitions](#start-definitions) section.
227236

@@ -489,7 +498,7 @@ defvaltype ::= bool
489498
| float32 | float64
490499
| char | string
491500
| (record (field <label> <valtype>)+)
492-
| (variant (case <id>? <label> <valtype>? (refines <id>)?)+)
501+
| (variant (case <id>? <label> <valtype>?)+)
493502
| (list <valtype>)
494503
| (tuple <valtype>+)
495504
| (flags <label>+)
@@ -520,7 +529,7 @@ externdesc ::= (<sort> (type <u32>) )
520529
| <functype>
521530
| <componenttype>
522531
| <instancetype>
523-
| (value <valtype>)
532+
| (value <valtype>) 🪙
524533
| (type <typebound>)
525534
typebound ::= (eq <typeidx>)
526535
| (sub resource)
@@ -574,13 +583,6 @@ through these canonical definitions. The `typeidx` immediate of a handle type
574583
must refer to a `resource` type (described below) that statically classifies
575584
the particular kinds of resources the handle can point to.
576585

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-
584586
The sets of values allowed for the remaining *specialized value types* are
585587
defined by the following mapping:
586588
```
@@ -649,7 +651,7 @@ references to out-of-line type definitions (via `(type <typeidx>)`) and inline
649651
type expressions that the text format desugars into out-of-line type
650652
definitions.
651653

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
653655
exported at instantiation time as described in the
654656
[start definitions](#start-definitions) section below.
655657

@@ -729,11 +731,7 @@ Like core modules, components have an up-front validation phase in which the
729731
definitions of a component are checked for basic consistency. Type checking
730732
is a central part of validation and, e.g., occurs when validating that the
731733
`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.
737735

738736
To incrementally describe how type-checking works, we'll start by asking how
739737
*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
766764
decoding, they all have the same AST.
767765

768766
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
785778
(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+
))
791803
)
792804
```
793805

@@ -1239,7 +1251,7 @@ See the [CanonicalABI.md](CanonicalABI.md#canonical-definitions) for detailed
12391251
definitions of each of these built-ins and their interactions.
12401252

12411253

1242-
### Start Definitions
1254+
### 🪙 Start Definitions
12431255

12441256
Like modules, components can have start functions that are called during
12451257
instantiation. Unlike modules, components can call start functions at multiple
@@ -1306,19 +1318,22 @@ exported). The grammar for imports and exports is:
13061318
import ::= (import <importname> bind-id(<externdesc>))
13071319
export ::= (export <id>? <exportname> <sortidx> <externdesc>?)
13081320
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>
13101327
importname ::= <exportname>
13111328
| <name> (url <string> <integrity>?)
13121329
| <name> (relative-url <string> <integrity>?)
13131330
| <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>?
13221337
verrange ::= <version>
13231338
| @*
13241339
| @{<verlower>}
@@ -1385,11 +1400,12 @@ host must locate the contents using the hash (e.g., using an [OCI Registry]).
13851400

13861401
The "registry" referred to by dependency names serves to map a hierarchical
13871402
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":
13931409
* a live registry (perhaps accessed via [`warg`])
13941410
* a local filesystem directory (perhaps containing vendored dependencies)
13951411
* 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
14151431
source language, thereby leveraging existing namespacing in the registry to
14161432
avoid conflicts in the source bindings. Note that, because of the mandatory `:`
14171433
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.
14201436

14211437
Components provide two options for naming exports, symmetric to the first two
14221438
options for naming imports:
@@ -1609,7 +1625,7 @@ For example, the following component:
16091625
;; a.wasm
16101626
(component
16111627
(import "one" (func))
1612-
(import "two" (value string))
1628+
(import "two" (value string)) 🪙
16131629
(import "three" (instance
16141630
(export "four" (instance
16151631
(export "five" (core module
@@ -1634,7 +1650,7 @@ could be successfully instantiated via:
16341650
```js
16351651
WebAssembly.instantiateStreaming(fetch('./a.wasm'), {
16361652
one: () => (),
1637-
two: "hi",
1653+
two: "hi", 🪙
16381654
three: {
16391655
four: {
16401656
five: await WebAssembly.compileStreaming(fetch('./b.wasm'))
@@ -1878,6 +1894,7 @@ and will be added over the coming months to complete the MVP proposal:
18781894
[stack-switching]: https://github.com/WebAssembly/stack-switching/blob/main/proposals/stack-switching/Overview.md
18791895
[esm-integration]: https://github.com/WebAssembly/esm-integration/tree/main/proposals/esm-integration
18801896
[gc]: https://github.com/WebAssembly/gc/blob/main/proposals/gc/MVP.md
1897+
[WASI Preview 2]: https://github.com/WebAssembly/WASI/tree/main/preview2
18811898

18821899
[Adapter Functions]: FutureFeatures.md#custom-abis-via-adapter-functions
18831900
[Canonical ABI]: CanonicalABI.md

0 commit comments

Comments
 (0)