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

Commit 114f619

Browse files
committed
[js-api] Add support for exceptions.
1 parent a5e87e4 commit 114f619

File tree

1 file changed

+186
-3
lines changed

1 file changed

+186
-3
lines changed

document/js-api/index.bs

Lines changed: 186 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ urlPrefix: https://webassembly.github.io/reference-types/core/; spec: WebAssembl
113113
text: ref.null
114114
text: ref.func
115115
text: ref.extern
116+
text: ref.exn
116117
text: function index; url: syntax/modules.html#syntax-funcidx
117118
text: function instance; url: exec/runtime.html#function-instances
118119
text: store_init; url: appendix/embedding.html#embed-store-init
@@ -149,6 +150,7 @@ urlPrefix: https://webassembly.github.io/reference-types/core/; spec: WebAssembl
149150
text: memory address; url: exec/runtime.html#syntax-memaddr
150151
text: global address; url: exec/runtime.html#syntax-globaladdr
151152
text: extern address; url: exec/runtime.html#syntax-externaddr
153+
text: event address; url: exec/runtime.html#syntax-eventaddr
152154
url: syntax/types.html#syntax-numtype
153155
text: i32
154156
text: i64
@@ -160,7 +162,10 @@ urlPrefix: https://webassembly.github.io/reference-types/core/; spec: WebAssembl
160162
text: externref
161163
text: function element; url: exec/runtime.html#syntax-funcelem
162164
text: import component; url: syntax/modules.html#imports
163-
text: external value; url: exec/runtime.html#syntax-externval
165+
url: exec/runtime.html#syntax-externval
166+
text: external value
167+
for: external value
168+
text: event
164169
text: host function; url: exec/runtime.html#syntax-hostfunc
165170
text: the instantiation algorithm; url: exec/modules.html#instantiation
166171
text: module; url: syntax/modules.html#syntax-module
@@ -172,6 +177,8 @@ urlPrefix: https://webassembly.github.io/reference-types/core/; spec: WebAssembl
172177
text: table
173178
text: mem
174179
text: global
180+
for: externtype
181+
text: event
175182
text: global type; url: syntax/types.html#syntax-globaltype
176183
url: syntax/types.html#syntax-mut
177184
text: var
@@ -184,10 +191,19 @@ urlPrefix: https://webassembly.github.io/reference-types/core/; spec: WebAssembl
184191
text: memaddrs; for: moduleinst; url: exec/runtime.html#syntax-moduleinst
185192
text: signed_64; url: exec/numerics.html#aux-signed
186193
text: sequence; url: syntax/conventions.html#grammar-notation
194+
text: exception; for: eventtype/attribute; url: syntax/types.html#syntax-eventtype
187195
urlPrefix: https://heycam.github.io/webidl/; spec: WebIDL
188196
type: dfn
189197
text: create a namespace object; url: create-a-namespace-object
198+
199+
urlPrefix: https://webassembly.github.io/reference-types/core/; spec: WebAssembly (reference types); type: dfn
200+
url: exec/runtime.html#values
201+
text: ref.extern
202+
203+
urlPrefix: https://webassembly.github.io/js-types/js-api/; spec: WebAssembly JS API (JS Type Reflection)
204+
type: abstract-op; text: FromValueType; url: abstract-opdef-fromvaluetype
190205
</pre>
206+
<!-- TODO remove reftypes ^ -->
191207

192208
<pre class='link-defaults'>
193209
spec:infra; type:dfn; text:list
@@ -391,6 +407,12 @@ A {{Module}} object represents a single WebAssembly module. Each {{Module}} obje
391407
1. Let |tableaddr| be |v|.\[[Table]].
392408
1. Let |externtable| be the [=external value=] [=external value|table=] |tableaddr|.
393409
1. [=list/Append=] |externtable| to |imports|.
410+
1. If |externtype| is of the form [=externtype/event=] |attribute| <var ignore>functype</var>,
411+
1. Assert: |attribute| is [=eventtype/attribute/exception=].
412+
1. If |v| does not [=implement=] {{Exception}}, throw a {{LinkError}} exception.
413+
1. Let |tag| be |v|.\[[Address]].
414+
1. Let |extern| be the [=external value=] [=external value/event=] |tag|.
415+
1. [=list/Append=] |extern| to |imports|.
394416
1. Return |imports|.
395417

396418
Note: This algorithm only verifies the right kind of JavaScript values are passed.
@@ -424,6 +446,12 @@ The verification of WebAssembly type requirements is deferred to the
424446
1. Let [=external value|table=] |tableaddr| be |externval|.
425447
1. Let |table| be [=create a Table object|a new Table object=] created from |tableaddr|.
426448
1. Let |value| be |table|.
449+
1. If |externtype| is of the form [=externtype/event=] |attribute| <var ignore>functype</var>,
450+
1. Assert: |attribute| is [=eventtype/attribute/exception=].
451+
1. Assert: |externval| is of the form [=external value/event=] |eventaddr|.
452+
1. Let [=external value/event=] |eventaddr| be |externval|.
453+
1. Let |exception| be [=create an Exception object|a new Exception object=] created from |eventaddr|.
454+
1. Let |value| be |exception|.
427455
1. Let |status| be ! [=CreateDataProperty=](|exportsObject|, |name|, |value|).
428456
1. Assert: |status| is true.
429457

@@ -515,7 +543,8 @@ enum ImportExportKind {
515543
"function",
516544
"table",
517545
"memory",
518-
"global"
546+
"global",
547+
"event"
519548
};
520549

521550
dictionary ModuleExportDescriptor {
@@ -545,6 +574,7 @@ interface Module {
545574
* "table" if |type| is of the form [=table=] <var ignore>tabletype</var>
546575
* "memory" if |type| is of the form [=mem=] <var ignore>memtype</var>
547576
* "global" if |type| is of the form [=global=] <var ignore>globaltype</var>
577+
* "event" if |type| is of the form [=externtype/event=] <var ignore>event</var>
548578
</div>
549579

550580
<div algorithm>
@@ -1007,6 +1037,12 @@ This slot holds a [=function address=] relative to the [=surrounding agent=]'s [
10071037
1. Let (|store|, |ret|) be the result of [=func_invoke=](|store|, |funcaddr|, |args|).
10081038
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
10091039
1. If |ret| is [=error=], throw an exception. This exception should be a WebAssembly {{RuntimeError}} exception, unless otherwise indicated by <a href="#errors">the WebAssembly error mapping</a>.
1040+
1. If |ret| is exception |exntag| |payload|, then
1041+
1. If |exntag| is the [=JavaScript exception tag=], then
1042+
1. Let « [=ref.extern=] |externaddr| » be |payload|.
1043+
1. Throw the result of [=retrieving an extern value=] from |externaddr|.
1044+
1. Let |exception| be [=create a RuntimeException object|a new RuntimeException=] for |exntag| and |payload|.
1045+
1. Throw |exception|.
10101046
1. Let |outArity| be the [=list/size=] of |ret|.
10111047
1. If |outArity| is 0, return undefined.
10121048
1. Otherwise, if |outArity| is 1, return [=ToJSValue=](|ret|[0]).
@@ -1057,7 +1093,14 @@ Note: Exported Functions do not have a \[[Construct]] method and thus it is not
10571093
1. [=Clean up after running a callback=] with |stored settings|.
10581094
1. [=Clean up after running script=] with |relevant settings|.
10591095
1. Assert: |result|.\[[Type]] is <emu-const>throw</emu-const> or <emu-const>normal</emu-const>.
1060-
1. If |result|.\[[Type]] is <emu-const>throw</emu-const>, then trigger a WebAssembly trap, and propagate |result|.\[[Value]] to the enclosing JavaScript.
1096+
1. If |result|.\[[Type]] is <emu-const>throw</emu-const>, then:
1097+
1. If |v| [=implements=] {{RuntimeException}},
1098+
1. Let |type| be |v|.\[[Type]].
1099+
1. Let |payload| be |v|.\[[Payload]].
1100+
1. Otherwise,
1101+
1. Let |type| be the [=JavaScript exception tag=].
1102+
1. Let |payload| be [=ToWebAssemblyValue=](|v|, [=externref=]).
1103+
1. [=WebAssembly/Throw=] with |type| and |payload|.
10611104
1. Otherwise, return |result|.\[[Value]].
10621105
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
10631106
1. Let (|store|, |funcaddr|) be [=func_alloc=](|store|, |functype|, |hostfunc|).
@@ -1126,6 +1169,146 @@ The algorithm <dfn>ToWebAssemblyValue</dfn>(|v|, |type|) coerces a JavaScript va
11261169

11271170
</div>
11281171

1172+
1173+
<h3 id="exceptions">Exceptions</h3>
1174+
1175+
The <dfn>exception_parameters</dfn> algorithm returns the [=list=] of types for a given
1176+
[=event address=].
1177+
1178+
<h4 id="exceptions-types">Exception types</h4>
1179+
1180+
<pre class="idl">
1181+
dictionary ExceptionType {
1182+
required sequence&lt;ValueType> parameters;
1183+
};
1184+
1185+
[LegacyNamespace=WebAssembly, Exposed=(Window,Worker,Worklet)]
1186+
interface Exception {
1187+
constructor(ExceptionType type);
1188+
ExceptionType type();
1189+
};
1190+
</pre>
1191+
1192+
An {{Exception}} value represents a type of exception.
1193+
1194+
The <dfn for=Exception>payload types</dfn> of an {{Exception}} |e| is
1195+
[=exception_parameters=](|e|.\[[Address]]).)
1196+
1197+
<div algorithm>
1198+
1199+
To <dfn>create an Exception object</dfn> from an [=event address=] |eventAddress|, perform the
1200+
following steps:
1201+
1202+
TODO: cache?
1203+
1204+
1. Let |exception| be a [=new=] {{Exception}}.
1205+
1. Set |exception|.\[[Address]] to |eventAddress|.
1206+
1. Return |exception|.
1207+
1208+
</div>
1209+
1210+
<div algorithm>
1211+
1212+
The <dfn method for="Exception">type()</dfn> method steps are:
1213+
1214+
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1215+
1. Let |parameters| be [=exception_parameters=](|store|, **this**.\[[Address]]).
1216+
1. Let |idlParameters| be «».
1217+
1. [=list/iterate|For each=] |type| of |parameters|,
1218+
1. [=list/Append=] [$FromValueType$](|type|) to |idlParameters|.
1219+
1. Return «[ "{{ExceptionType/parameters}}" → |idlParameters| ]».
1220+
1221+
</div>
1222+
1223+
1224+
<h4 id="runtime-exceptions">Runtime exceptions</h4>
1225+
1226+
<pre class="idl">
1227+
[LegacyNamespace=WebAssembly, Exposed=(Window,Worker,Worklet)]
1228+
interface RuntimeException {
1229+
constructor(Exception exceptionType, sequence&lt;any> payload);
1230+
any getArg(Exception exceptionType, unsigned long index);
1231+
boolean is(Exception exceptionType);
1232+
};
1233+
</pre>
1234+
1235+
A {{RuntimeException}} value represents an exception.
1236+
1237+
<div algorithm>
1238+
1239+
To <dfn>create a RuntimeException object</dfn> from an [=event address=] |eventAddress| and [=list=]
1240+
of WebAssembly values |payload|, perform the following steps:
1241+
1242+
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1243+
1. Let |types| be [=exception_parameters=](|store|, |eventAddress|).
1244+
1. Assert: |types|'s [=list/size=] is |payload|'s [=list/size=].
1245+
1. [=list/iterate|For each=] |value| and |resultType| of |payload| and |types|, paired linearly,
1246+
1. Assert: |value|'s type matches |resultType|.
1247+
1. Let |exception| be a [=new=] {{RuntimeException}}.
1248+
1. Set |exception|.\[[Type]] to |eventAddress|.
1249+
1. Set |exception|.\[[Payload]] to |payload|.
1250+
1. Return |exception|.
1251+
1252+
</div>
1253+
1254+
<div algorithm>
1255+
1256+
The <dfn constructor for=RuntimeException
1257+
lt="RuntimeException(exceptionType, payload)">new RuntimeException(|exceptionType|, |payload|)</dfn>
1258+
constructor steps are:
1259+
1260+
1. Let |types| be |exceptionType|'s [=Exception/payload types=].
1261+
1. If |types|'s [=list/size=] is not |payload|'s [=list/size=],
1262+
1. Throw a {{TypeError}}.
1263+
1. Let |wasmPayload| be « ».
1264+
1. [=list/iterate|For each=] |value| and |resultType| of |payload| and |types|, paired linearly,
1265+
1. [=list/Append=] ? [=ToWebAssemblyValue=](|value|, |resultType|) to |wasmPayload|.
1266+
1. Set **this**.\[[Type]] to |exceptionType|.\[[Address]].
1267+
1. Set **this**.\[[Payload]] to |wasmPayload|.
1268+
1269+
</div>
1270+
1271+
<div algorithm>
1272+
1273+
The <dfn method for="RuntimeException">getArg(|exceptionType|, |index|)</dfn> method steps are:
1274+
1275+
1. If **this**.\[[Type]] is not equal to |exceptionType|.\[[Address]],
1276+
1. Throw a {{TypeError}}.
1277+
1. Let |payload| be **this**.\[[Payload]].
1278+
1. If |index| ≥ |payload|'s [=list/size=],
1279+
1. Throw a {{TypeError}}.
1280+
1. Return [=ToJSValue=](|payload|[|index|]).
1281+
1282+
</div>
1283+
1284+
<div algorithm>
1285+
1286+
The <dfn method for="RuntimeException">is(|exceptionType|)</dfn> method steps are:
1287+
1288+
1. If **this**.\[[Type]] is not equal to |exceptionType|.\[[Address]],
1289+
1. Return false.
1290+
1. Return true.
1291+
1292+
</div>
1293+
1294+
<h4 id="js-exceptions">JavaScript exceptions</h4>
1295+
1296+
The <dfn>JavaScript exception tag</dfn> is an [=event address=] reserved by this
1297+
specification to distinguish exceptions originating from JavaScript.
1298+
1299+
Issue: Should it be possible for `br_on_exn` to extract the payload from an exception with this tag?
1300+
1301+
<div algorithm>
1302+
1303+
To <dfn for=WebAssembly>throw</dfn> with an [=event address=] |type| and matching [=list=] of WebAssembly values |payload|, perform the following steps:
1304+
1305+
1. Unwind the stack until reaching the *catching try block* given |type|.
1306+
1. Invoke the catch block with |payload|.
1307+
1308+
Note: This algorithm is expected to be moved into the core specification.
1309+
1310+
</div>
1311+
11291312
<h3 id="error-objects">Error Objects</h3>
11301313

11311314
WebAssembly defines the following Error classes: <dfn exception>CompileError</dfn>, <dfn exception>LinkError</dfn>, and <dfn exception>RuntimeError</dfn>.

0 commit comments

Comments
 (0)