Skip to content

Commit d095e2f

Browse files
authored
Rename to version-suffix, tighten rules, add tests (#738)
Resolves #735
1 parent 0220da8 commit d095e2f

5 files changed

Lines changed: 275 additions & 35 deletions

File tree

‎design/mvp/Binary.md‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ nameattributes ::= 0x00 len:<u32> en:<externname> => "en"
407407
| 0x01 len:<u32> en:<externname> => "en" (if len = |en|)
408408
| 0x02 len:<u32> en:<externname> a*:vec(<attribute>) => "en" a* (if len = |en|) 🏷️/🔗
409409
attribute ::= 0x00 len:<u32> in:<interfacename> => (implements "in") (if len = |in|) 🏷️
410-
| 0x01 len:<u32> vs:<semversuffix> => (versionsuffix "vs") (if len = |vs|) 🔗
410+
| 0x01 len:<u32> s:<semversuffix> => (version-suffix "s") (if len = |vs|) 🔗
411411
| 0x02 n:<name> => (external-id n) 🏷️
412412
```
413413

@@ -469,11 +469,11 @@ Notes:
469469
* 📡 Validation of `[set]` names requires that the function have either no
470470
result type or a result type of `(result (error $E)?)` (with no value type).
471471
* 🔀/📡 Functions with `[get]` or `[set]` names must not be `async`.
472-
* 🔗 Validation requires that `versionsuffix` is preceded by an `interfaceversion`
473-
matching `canonversion` and that the concatenation of the `canonversion` and
474-
the `versionsuffix` results in a `valid semver` as defined by
475-
[https://semver.org](https://semver.org/). A `versionsuffix` is otherwise
476-
ignored for validation except to improve diagnostic messages.
472+
* 🔗 Validation requires that a `version-suffix` is only present on
473+
`instance`-typed imports or exports that have either an `implements`
474+
attribute or an `interfacename` name.
475+
* 🔗 Validation requires that every `interfacename` with an `interfaceversion`
476+
satisfies the [canonical interface name] rules.
477477

478478
## 🪙 Value Definitions
479479

@@ -600,6 +600,7 @@ named once.
600600
[`core:rectype]: https://webassembly.github.io/gc/core/binary/types.html#recursive-types
601601

602602
[Strongly-unique]: Explainer.md#name-uniqueness
603+
[Canonical Interface Name]: Explainer.md#-canonical-interface-name
603604

604605
[type-imports]: https://github.com/WebAssembly/proposal-type-imports/blob/master/proposals/type-imports/Overview.md
605606
[module-linking]: https://github.com/WebAssembly/module-linking/blob/main/proposals/module-linking/Explainer.md

‎design/mvp/Explainer.md‎

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -645,8 +645,8 @@ instancedecl ::= core-prefix(<core:type>)
645645
| <type>
646646
| <alias>
647647
| <exportdecl>
648-
importdecl ::= (import <externnamelit> <attribute>* bind-id(<externtype>))
649-
exportdecl ::= (export <externnamelit> <attribute>* bind-id(<externtype>))
648+
importdecl ::= (import <externnamelit> <attributes> bind-id(<externtype>))
649+
exportdecl ::= (export <externnamelit> <attributes> bind-id(<externtype>))
650650
externtype ::= (<sort> (type <idx>) )
651651
| core-prefix(<core:moduletype>)
652652
| <functype>
@@ -1121,9 +1121,10 @@ and `$C1` is a subtype of `$C2`:
11211121
)
11221122
```
11231123

1124-
🏷️/🔗 Note that all `attribute`s on `import`s and `export`s are ignored by type
1125-
checking and so any `external-id`, `implements` or `versionsuffix` attribute can
1126-
be added to any of the `func`s above without changing the result.
1124+
🏷️/🔗 Note that all `attributes` on `import`s and `export`s are ignored by type
1125+
checking and so adding, removing or changing any `external-id` attribute on the
1126+
`func`s above (or any `implements` or `version-suffix` attribute on `instance`
1127+
imports or exports) does not change the result.
11271128

11281129
When we next consider type imports and exports, there are two distinct
11291130
subcases of `typebound` to consider: `eq` and `sub`.
@@ -2661,17 +2662,15 @@ exported (e.g., `(export $x "x" (func $f))` binds a new identifier `$x`).
26612662

26622663
Given this, the syntax of imports and exports are defined as follows:
26632664
```ebnf
2664-
import ::= (import <externnamelit> <attribute>* bind-id(<externtype>))
2665-
export ::= (export <id>? <externnamelit> <attribute>* <externidx> <externtype>?)
2666-
attribute ::= <versionsuffix> 🔗
2667-
| <implements> 🏷️
2668-
| <externid> 🏷️
2669-
versionsuffix ::= (versionsuffix <semversuffixlit>) 🔗
2665+
import ::= (import <externnamelit> <attributes> bind-id(<externtype>))
2666+
export ::= (export <id>? <externnamelit> <attributes> <externidx> <externtype>?)
2667+
attributes ::= <implements>? <versionsuffix>? <externid>?
26702668
implements ::= (implements <interfacenamelit>) 🏷️
2669+
versionsuffix ::= (version-suffix <semversuffixlit>) 🔗
26712670
externid ::= (external-id <name>) 🏷️
26722671
```
26732672
Imports and exports both have a *name* (`externnamelit`) and a list of
2674-
*attributes* (`attribute*`). Imports always include a type (`externtype`).
2673+
*attributes* (`attributes`). Imports always include a type (`externtype`).
26752674
Exports always refer to a preceding definition (`externidx`) whose type is used
26762675
by default as the type of the export. However, this "inferred" type can be
26772676
overridden with an optional type ascription (`externtype`) which must be
@@ -2689,10 +2688,19 @@ and exports and instead provide extra semantic information *about* imports and
26892688
exports that hosts or tools can automatically interpret to determine *how* to
26902689
supply imports and call exports. In particular:
26912690

2692-
🔗 The `versionsuffix` attribute provides the minor/patch/pre-release/build
2693-
information that was stripped from the [Canonical interface name](#-canonical-interface-name)
2694-
so that this information can be used in error messages to reconstruct the full
2695-
original semantic version.
2691+
🔗 The `version-suffix` attribute provides the minor/patch/build information that
2692+
was stripped from the [Canonical interface name](#-canonical-interface-name) so
2693+
that this information can be used in error messages to reconstruct the full
2694+
original semantic version. A `version-suffix` may only be attached to an
2695+
`instance` import or export and applies to the `interfacename` of the
2696+
`implements` attribute, if present, and otherwise to the `interfacename` of the
2697+
import or export itself. For example:
2698+
```wat
2699+
(component
2700+
(import "wasi:http/types@0.2" (version-suffix ".6") (instance ...))
2701+
(import "primary" (implements "wasi:keyvalue/store@0.2") (version-suffix ".1") (instance ...))
2702+
)
2703+
```
26962704

26972705
🏷️ The `implements` attribute indicates that an imported or exported `instance`
26982706
implements a particular WIT interface. This enables a component to semantically
@@ -2780,8 +2788,9 @@ canonversion ::= [1-9] [0-9]* 🔗
27802788
| '0.' [1-9] [0-9]* 🔗
27812789
| '0.0.' [1-9] [0-9]* 🔗
27822790
| '0.0.0' 🔗
2791+
| <version core> '-' <pre-release> 🔗
27832792
semversuffixlit ::= '"' <semversuffix> '"' 🔗
2784-
semversuffix ::= [0-9A-Za-z.+-]* 🔗
2793+
semversuffix ::= [0-9A-Za-z.+-]+ 🔗
27852794
```
27862795
The names of component imports and exports provide two options:
27872796
* a **plain name** that leaves it up to the developer to "read the docs"
@@ -2824,8 +2833,9 @@ annotations trigger additional type-validation rules (listed in detail in
28242833
parameter from `[method]`) whose type matches the getter's return type, and
28252834
must return either nothing or `(result (error <valtype>)?)`.
28262835

2827-
The `valid semver` production is as defined by the [Semantic Versioning 2.0]
2828-
spec and is meant to be interpreted according to that specification. The use of
2836+
The `valid semver` production (along with its `version core` and `pre-release`
2837+
sub-productions) is as defined by the [Semantic Versioning 2.0] spec and is
2838+
meant to be interpreted according to that specification. The use of
28292839
`valid semver` in `interfaceversion` is temporary for backward compatibility;
28302840
see [Canonical interface name](#-canonical-interface-name) below (🔗).
28312841

@@ -2991,12 +3001,19 @@ the `<major>.<minor>.<patch>(-<pre>)(+<build>)` syntax of [Semantic Versioning
29913001
- `0.0.1+sha.5114f85` &rarr; `0.0.1` / `+sha.5114f85`
29923002

29933003
When a version is canonicalized, any `semversuffix` that was split off of the
2994-
version should be preserved in the `versionsuffix` field of any resulting
2995-
`import`s and `export`s. This gives component runtimes and other tools access to
2996-
the original version for error messages, documentation, and other development
2997-
purposes. Where a `versionsuffix` is present the preceding `interfacename` must
2998-
have a `canonversion`, and the concatenation of the `canonversion` and
2999-
`versionsuffix` must be a `valid semver`.
3004+
version must be preserved in the `version-suffix` attribute of any resulting
3005+
`import`s and `export`s to give component runtimes and other tools access to the
3006+
original version for error messages, documentation, and other development
3007+
purposes. Validation checks this by requiring that the `interfaceversion`
3008+
concatenated with the `version-suffix` (if present) is a `valid semver` and that,
3009+
when a `version-suffix` is present, canonicalizing the concatenated `valid semver`
3010+
splits it into exactly the `interfaceversion` and the `version-suffix`. Thus,
3011+
for example:
3012+
- `a:b/c@1` is invalid (`1` is not a `valid semver`)
3013+
- `a:b/c@1` with `.2.3` and `a:b/c@0.0.1-alpha` with `+sha` are valid
3014+
- `a:b/c@1` with `.2.3-alpha` is invalid (`1.2.3-alpha` is not split)
3015+
- `a:b/c@1.2` with `.3` and `a:b/c@1.2.3` with `+sha` are invalid (`1.2.3` and
3016+
`1.2.3+sha` are split after `1`)
30003017

30013018
For compatibility with older versions of this spec, non-canonical
30023019
`interfacename`s (with `interfaceversion`s matching any `valid semver`) are

‎test/README.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ This directory contains Component Model reference tests, grouped by functionalit
66

77
A single `.wast` test can be run with full backtrace on trap via:
88
```
9-
WASMTIME_BACKTRACE_DETAILS=1 WAST_STRICT_COMPONENT_INDICES=1 wasmtime wast -W component-model-more-async-builtins -W component-model-threading -W component-model-async-stackful -W component-model-implements -W component-model-fixed-length-lists -W component-model-map the-test.wast
9+
WASMTIME_BACKTRACE_DETAILS=1 WAST_STRICT_COMPONENT_INDICES=1 wasmtime wast -W component-model-more-async-builtins -W component-model-threading -W component-model-async-stackful -W component-model-implements -W component-model-fixed-length-lists -W component-model-map -W component-model-canonical-names the-test.wast
1010
```
1111

1212
Sometimes test land ahead of the implementation and fail for a while. These
1313
tests are listed in 'nyi.txt' so that they can be filtered out. Thus, a simple
1414
way to run all the reference tests is:
1515
```
16-
find . -name "*.wast" | grep -vxFf nyi.txt | WAST_STRICT_COMPONENT_INDICES=1 xargs wasmtime wast -W component-model-more-async-builtins -W component-model-threading -W component-model-async-stackful -W component-model-implements -W component-model-fixed-length-lists -W component-model-map
16+
find . -name "*.wast" | grep -vxFf nyi.txt | WAST_STRICT_COMPONENT_INDICES=1 xargs wasmtime wast -W component-model-more-async-builtins -W component-model-threading -W component-model-async-stackful -W component-model-implements -W component-model-fixed-length-lists -W component-model-map -W component-model-canonical-names
1717
```

‎test/binary/binary.wast‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,15 +1319,21 @@
13191319
"\07\03" ;; type section (3 bytes)
13201320
"\01" ;; 1 type
13211321
"\42\00" ;; empty instancetype
1322-
"\0a\2f" ;; import section (47 bytes)
1323-
"\02" ;; 2 imports
1322+
"\0a\41" ;; import section (65 bytes)
1323+
"\03" ;; 3 imports
13241324
"\02" ;; externname with attributes
13251325
"\02i1" ;; name "i1"
13261326
"\01" ;; 1 attribute:
13271327
"\00" ;; 0x00 implements:
13281328
"\0cmy:dep/iface" ;; name "my:dep/iface"
13291329
"\05\00" ;; instance (type 0)
13301330
"\02" ;; externname with attributes
1331+
"\07a:b/c@1" ;; name "a:b/c@1"
1332+
"\01" ;; 1 attribute:
1333+
"\01" ;; 0x01 version-suffix:
1334+
"\04.2.3" ;; ".2.3"
1335+
"\05\00" ;; instance (type 0)
1336+
"\02" ;; externname with attributes
13311337
"\02i2" ;; name "i2"
13321338
"\01" ;; 1 attribute:
13331339
"\02" ;; 0x02 external-id:

0 commit comments

Comments
 (0)