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

Commit deb2800

Browse files
committed
[js-api] Add support for exceptions.
1 parent 0c0adbe commit deb2800

File tree

1 file changed

+178
-3
lines changed

1 file changed

+178
-3
lines changed

document/js-api/index.bs

Lines changed: 178 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ urlPrefix: https://webassembly.github.io/reference-types/core/; spec: WebAssembl
149149
text: memory address; url: exec/runtime.html#syntax-memaddr
150150
text: global address; url: exec/runtime.html#syntax-globaladdr
151151
text: extern address; url: exec/runtime.html#syntax-externaddr
152+
text: event address; url: exec/runtime.html#syntax-eventaddr
152153
url: syntax/types.html#syntax-numtype
153154
text: i32
154155
text: i64
@@ -160,7 +161,10 @@ urlPrefix: https://webassembly.github.io/reference-types/core/; spec: WebAssembl
160161
text: externref
161162
text: function element; url: exec/runtime.html#syntax-funcelem
162163
text: import component; url: syntax/modules.html#imports
163-
text: external value; url: exec/runtime.html#syntax-externval
164+
url: exec/runtime.html#syntax-externval
165+
text: external value
166+
for: external value
167+
text: event
164168
text: host function; url: exec/runtime.html#syntax-hostfunc
165169
text: the instantiation algorithm; url: exec/modules.html#instantiation
166170
text: module; url: syntax/modules.html#syntax-module
@@ -172,6 +176,8 @@ urlPrefix: https://webassembly.github.io/reference-types/core/; spec: WebAssembl
172176
text: table
173177
text: mem
174178
text: global
179+
for: externtype
180+
text: event
175181
text: global type; url: syntax/types.html#syntax-globaltype
176182
url: syntax/types.html#syntax-mut
177183
text: var
@@ -184,9 +190,12 @@ urlPrefix: https://webassembly.github.io/reference-types/core/; spec: WebAssembl
184190
text: memaddrs; for: moduleinst; url: exec/runtime.html#syntax-moduleinst
185191
text: signed_64; url: exec/numerics.html#aux-signed
186192
text: sequence; url: syntax/conventions.html#grammar-notation
193+
text: exception; for: eventtype/attribute; url: syntax/types.html#syntax-eventtype
187194
urlPrefix: https://heycam.github.io/webidl/; spec: WebIDL
188195
type: dfn
189196
text: create a namespace object; url: create-a-namespace-object
197+
urlPrefix: https://webassembly.github.io/js-types/js-api/; spec: WebAssembly JS API (JS Type Reflection)
198+
type: abstract-op; text: FromValueType; url: abstract-opdef-fromvaluetype
190199
</pre>
191200

192201
<pre class='link-defaults'>
@@ -391,6 +400,12 @@ A {{Module}} object represents a single WebAssembly module. Each {{Module}} obje
391400
1. Let |tableaddr| be |v|.\[[Table]].
392401
1. Let |externtable| be the [=external value=] [=external value|table=] |tableaddr|.
393402
1. [=list/Append=] |externtable| to |imports|.
403+
1. If |externtype| is of the form [=externtype/event=] |attribute| <var ignore>functype</var>,
404+
1. Assert: |attribute| is [=eventtype/attribute/exception=].
405+
1. If |v| does not [=implement=] {{Exception}}, throw a {{LinkError}} exception.
406+
1. Let |tag| be |v|.\[[Address]].
407+
1. Let |extern| be the [=external value=] [=external value/event=] |tag|.
408+
1. [=list/Append=] |extern| to |imports|.
394409
1. Return |imports|.
395410

396411
Note: This algorithm only verifies the right kind of JavaScript values are passed.
@@ -424,6 +439,12 @@ The verification of WebAssembly type requirements is deferred to the
424439
1. Let [=external value|table=] |tableaddr| be |externval|.
425440
1. Let |table| be [=create a Table object|a new Table object=] created from |tableaddr|.
426441
1. Let |value| be |table|.
442+
1. If |externtype| is of the form [=externtype/event=] |attribute| <var ignore>functype</var>,
443+
1. Assert: |attribute| is [=eventtype/attribute/exception=].
444+
1. Assert: |externval| is of the form [=external value/event=] |eventaddr|.
445+
1. Let [=external value/event=] |eventaddr| be |externval|.
446+
1. Let |exception| be [=create an Exception object|a new Exception object=] created from |eventaddr|.
447+
1. Let |value| be |exception|.
427448
1. Let |status| be ! [=CreateDataProperty=](|exportsObject|, |name|, |value|).
428449
1. Assert: |status| is true.
429450

@@ -515,7 +536,8 @@ enum ImportExportKind {
515536
"function",
516537
"table",
517538
"memory",
518-
"global"
539+
"global",
540+
"event"
519541
};
520542

521543
dictionary ModuleExportDescriptor {
@@ -545,6 +567,7 @@ interface Module {
545567
* "table" if |type| is of the form [=table=] <var ignore>tabletype</var>
546568
* "memory" if |type| is of the form [=mem=] <var ignore>memtype</var>
547569
* "global" if |type| is of the form [=global=] <var ignore>globaltype</var>
570+
* "event" if |type| is of the form [=externtype/event=] <var ignore>event</var>
548571
</div>
549572

550573
<div algorithm>
@@ -1005,8 +1028,15 @@ This slot holds a [=function address=] relative to the [=surrounding agent=]'s [
10051028
1. [=list/Append=] [=ToWebAssemblyValue=](|arg|, |t|) to |args|.
10061029
1. Set |i| to |i| + 1.
10071030
1. Let (|store|, |ret|) be the result of [=func_invoke=](|store|, |funcaddr|, |args|).
1031+
1. Note: The expectation is that [=func_invoke=] will be updated to return (|store|, <var ignore>val</var>* | [=error=] | (exception |exntag| |payload|)).
10081032
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
10091033
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>.
1034+
1. If |ret| is exception |exntag| |payload|, then
1035+
1. If |exntag| is the [=JavaScript exception tag=], then
1036+
1. Let « [=ref.extern=] |externaddr| » be |payload|.
1037+
1. Throw the result of [=retrieving an extern value=] from |externaddr|.
1038+
1. Let |exception| be [=create a RuntimeException object|a new RuntimeException=] for |exntag| and |payload|.
1039+
1. Throw |exception|.
10101040
1. Let |outArity| be the [=list/size=] of |ret|.
10111041
1. If |outArity| is 0, return undefined.
10121042
1. Otherwise, if |outArity| is 1, return [=ToJSValue=](|ret|[0]).
@@ -1057,7 +1087,14 @@ Note: Exported Functions do not have a \[[Construct]] method and thus it is not
10571087
1. [=Clean up after running a callback=] with |stored settings|.
10581088
1. [=Clean up after running script=] with |relevant settings|.
10591089
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.
1090+
1. If |result|.\[[Type]] is <emu-const>throw</emu-const>, then:
1091+
1. If |v| [=implements=] {{RuntimeException}},
1092+
1. Let |type| be |v|.\[[Type]].
1093+
1. Let |payload| be |v|.\[[Payload]].
1094+
1. Otherwise,
1095+
1. Let |type| be the [=JavaScript exception tag=].
1096+
1. Let |payload| be [=ToWebAssemblyValue=](|v|, [=externref=]).
1097+
1. [=WebAssembly/Throw=] with |type| and |payload|.
10611098
1. Otherwise, return |result|.\[[Value]].
10621099
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
10631100
1. Let (|store|, |funcaddr|) be [=func_alloc=](|store|, |functype|, |hostfunc|).
@@ -1126,6 +1163,144 @@ The algorithm <dfn>ToWebAssemblyValue</dfn>(|v|, |type|) coerces a JavaScript va
11261163

11271164
</div>
11281165

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

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

0 commit comments

Comments
 (0)