Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit 322e948

Browse files
authored
Merge pull request #522 from takikawa/default_value
[js-api][test] Refine DefaultValue for new reference types
2 parents 2361fee + d5a49d2 commit 322e948

File tree

5 files changed

+74
-12
lines changed

5 files changed

+74
-12
lines changed

document/core/appendix/embedding.rst

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -630,11 +630,12 @@ Globals
630630
\end{array}
631631
632632
633-
.. index:: reference, reference type
633+
.. index:: reference, reference type, value type, value
634634
.. _embed-ref-type:
635+
.. _embed-val-default:
635636

636-
References
637-
~~~~~~~~~~
637+
Values
638+
~~~~~~
638639

639640
:math:`\F{ref\_type}(\store, \reff) : \reftype`
640641
...............................................
@@ -656,6 +657,20 @@ References
656657
In such cases, this function may return a less precise supertype.
657658

658659

660+
:math:`\F{val\_default}(\valtype) : \val`
661+
...............................................
662+
663+
1. If :math:`\default_{valtype}` is not defined, then return :math:`\ERROR`.
664+
665+
1. Else, return the :ref:`value <syntax-val>` :math:`\default_{valtype}`.
666+
667+
.. math::
668+
\begin{array}{lclll}
669+
\F{val\_default}(t) &=& v && (\iff \default_t = v) \\
670+
\F{val\_default}(t) &=& \ERROR && (\iff \default_t = \epsilon) \\
671+
\end{array}
672+
673+
659674
.. index:: value type, external type, subtyping
660675
.. _embed-match-valtype:
661676
.. _embed-match-externtype:

document/js-api/index.bs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df
115115
text: global_read; url: appendix/embedding.html#embed-global-read
116116
text: global_write; url: appendix/embedding.html#embed-global-write
117117
text: ref_type; url: appendix/embedding.html#embed-ref-type
118+
text: val_default; url: appendix/embedding.html#embed-val-default
118119
text: match_valtype; url: appendix/embedding.html#embed-match-valtype
119120
text: error; url: appendix/embedding.html#embed-error
120121
text: store; url: exec/runtime.html#syntax-store
@@ -764,6 +765,7 @@ Each {{Table}} object has a \[[Table]] internal slot, which is a [=table address
764765
1. If |maximum| is not empty and |maximum| &lt; |initial|, throw a {{RangeError}} exception.
765766
1. If |value| is missing,
766767
1. Let |ref| be [=DefaultValue=](|elementType|).
768+
1. Assert: |ref| is not [=error=].
767769
1. Otherwise,
768770
1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementType|).
769771
1. Let |type| be the [=table type=] {[=table type|min=] |initial|, [=table type|max=] |maximum|} |elementType|.
@@ -781,6 +783,7 @@ Each {{Table}} object has a \[[Table]] internal slot, which is a [=table address
781783
1. Let (<var ignore>limits</var>, |elementType|) be [=table_type=](|tableaddr|).
782784
1. If |value| is missing,
783785
1. Let |ref| be [=DefaultValue=](|elementType|).
786+
1. If |ref| is [=error=], throw a {{TypeError}} exception.
784787
1. Otherwise,
785788
1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementType|).
786789
1. Let |result| be [=table_grow=](|store|, |tableaddr|, |delta|, |ref|).
@@ -814,6 +817,7 @@ Each {{Table}} object has a \[[Table]] internal slot, which is a [=table address
814817
1. Let (<var ignore>limits</var>, |elementType|) be [=table_type=](|tableaddr|).
815818
1. If |value| is missing,
816819
1. Let |ref| be [=DefaultValue=](|elementType|).
820+
1. If |ref| is [=error=], throw a {{TypeError}} exception.
817821
1. Otherwise,
818822
1. Let |ref| be [=?=] [=ToWebAssemblyValue=](|value|, |elementType|).
819823
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
@@ -890,13 +894,8 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
890894

891895
<div algorithm>
892896
The algorithm <dfn>DefaultValue</dfn>(|valuetype|) performs the following steps:
893-
1. If |valuetype| equals [=i32=], return [=i32.const=] 0.
894-
1. If |valuetype| equals [=i64=], return [=i64.const=] 0.
895-
1. If |valuetype| equals [=f32=], return [=f32.const=] 0.
896-
1. If |valuetype| equals [=f64=], return [=f64.const=] 0.
897-
1. If |valuetype| equals [=funcref=], return [=ref.null=] [=funcref=].
898897
1. If |valuetype| equals [=externref=], return [=ToWebAssemblyValue=](undefined, |valuetype|).
899-
1. Assert: This step is not reached.
898+
1. Return [=val_default=](|valuetype|).
900899
</div>
901900

902901
<div algorithm>
@@ -907,6 +906,7 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
907906
1. Throw a {{TypeError}} exception.
908907
1. If |v| is missing,
909908
1. Let |value| be [=DefaultValue=](|valuetype|).
909+
1. Assert: |value| is not [=error=].
910910
1. Otherwise,
911911
1. Let |value| be [=ToWebAssemblyValue=](|v|, |valuetype|).
912912
1. If |mutable| is true, let |globaltype| be [=var=] |valuetype|; otherwise, let |globaltype| be [=const=] |valuetype|.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// META: global=window,dedicatedworker,jsshell
2+
// META: script=/wasm/jsapi/wasm-module-builder.js
3+
4+
let exports = {};
5+
setup(() => {
6+
const builder = new WasmModuleBuilder();
7+
8+
builder.addTable(wasmRefType(kWasmAnyRef), 10, 20, [...wasmI32Const(42), ...GCInstr(kExprRefI31)])
9+
.exportAs("tableAnyNonNullable");
10+
builder.addTable(wasmRefNullType(kWasmAnyRef), 10, 20)
11+
.exportAs("tableAnyNullable");
12+
13+
const buffer = builder.toBuffer();
14+
const module = new WebAssembly.Module(buffer);
15+
const instance = new WebAssembly.Instance(module, {});
16+
exports = instance.exports;
17+
});
18+
19+
test(() => {
20+
exports.tableAnyNullable.grow(5);
21+
for (let i = 0; i < 5; i++)
22+
assert_equals(exports.tableAnyNullable.get(10 + i), null);
23+
}, "grow (nullable anyref)");
24+
25+
test(() => {
26+
assert_throws_js(TypeError, () => { exports.tableAnyNonNullable.grow(5); });
27+
exports.tableAnyNonNullable.grow(5, "foo");
28+
for (let i = 0; i < 5; i++)
29+
assert_equals(exports.tableAnyNonNullable.get(10 + i), "foo");
30+
}, "grow (non-nullable anyref)");
31+
32+
test(() => {
33+
for (let i = 0; i < exports.tableAnyNullable.length; i++) {
34+
exports.tableAnyNullable.set(i);
35+
assert_equals(exports.tableAnyNullable.get(i), null);
36+
}
37+
}, "set (nullable anyref)");
38+
39+
test(() => {
40+
for (let i = 0; i < exports.tableAnyNonNullable.length; i++) {
41+
assert_throws_js(TypeError, () => { exports.tableAnyNonNullable.set(i); });
42+
}
43+
}, "set (non-nullable anyref)");

test/js-api/gc/i31.tentative.any.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ setup(() => {
1111
builder
1212
.addFunction("makeI31", makeSig_r_x(i31Ref, kWasmI32))
1313
.addBody([kExprLocalGet, 0,
14-
...GCInstr(kExprI31New)])
14+
...GCInstr(kExprRefI31)])
1515
.exportFunc();
1616

1717
builder
@@ -33,7 +33,7 @@ setup(() => {
3333
.exportFunc();
3434

3535
builder
36-
.addGlobal(i31NullableRef, true, [...wasmI32Const(0), ...GCInstr(kExprI31New)])
36+
.addGlobal(i31NullableRef, true, [...wasmI32Const(0), ...GCInstr(kExprRefI31)])
3737
builder
3838
.addExportOfKind("i31Global", kExternalGlobal, 0);
3939

test/js-api/wasm-module-builder.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ let kExprBrOnCast = 0x18;
456456
let kExprBrOnCastFail = 0x19;
457457
let kExprExternInternalize = 0x1a;
458458
let kExprExternExternalize = 0x1b;
459-
let kExprI31New = 0x1c;
459+
let kExprRefI31 = 0x1c;
460460
let kExprI31GetS = 0x1d;
461461
let kExprI31GetU = 0x1e;
462462

@@ -1199,6 +1199,10 @@ class WasmModuleBuilder {
11991199
binary.emit_section(kTableSectionCode, section => {
12001200
section.emit_u32v(wasm.tables.length);
12011201
for (let table of wasm.tables) {
1202+
if (table.has_init) {
1203+
section.emit_u8(0x40); // "has initializer"
1204+
section.emit_u8(0x00); // Reserved byte.
1205+
}
12021206
section.emit_type(table.type);
12031207
section.emit_u8(table.has_max);
12041208
section.emit_u32v(table.initial_size);

0 commit comments

Comments
 (0)