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

Commit eb92b3a

Browse files
committed
fixup! [js-api] Add support for exceptions.
1 parent 789acfa commit eb92b3a

File tree

1 file changed

+113
-19
lines changed

1 file changed

+113
-19
lines changed

document/js-api/index.bs

Lines changed: 113 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df
108108
text: ref.null
109109
text: ref.func
110110
text: ref.host
111+
text: ref.exn
111112
text: function index; url: syntax/modules.html#syntax-funcidx
112113
text: function instance; url: exec/runtime.html#function-instances
113114
text: store_init; url: appendix/embedding.html#embed-store-init
@@ -144,6 +145,7 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df
144145
text: memory address; url: exec/runtime.html#syntax-memaddr
145146
text: global address; url: exec/runtime.html#syntax-globaladdr
146147
text: host address; url: exec/runtime.html#syntax-hostaddr
148+
text: event address; url: exec/runtime.html#syntax-eventaddr
147149
url: syntax/types.html#syntax-numtype
148150
text: 𝗂𝟥𝟤
149151
text: 𝗂𝟨𝟦
@@ -153,9 +155,13 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df
153155
text: anyref
154156
text: funcref
155157
text: nullref
158+
text: exnref
156159
text: function element; url: exec/runtime.html#syntax-funcelem
157160
text: import component; url: syntax/modules.html#imports
158-
text: external value; url: exec/runtime.html#syntax-externval
161+
url: exec/runtime.html#syntax-externval
162+
text: external value
163+
for: external value
164+
text: event
159165
text: host function; url: exec/runtime.html#syntax-hostfunc
160166
text: the instantiation algorithm; url: exec/modules.html#instantiation
161167
text: module; url: syntax/modules.html#syntax-module
@@ -167,6 +173,8 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df
167173
text: 𝗍𝖺𝖻𝗅𝖾
168174
text: 𝗆𝖾𝗆
169175
text: 𝗀𝗅𝗈𝖻𝖺𝗅
176+
for: externtype
177+
text: event
170178
text: global type; url: syntax/types.html#syntax-globaltype
171179
url: syntax/types.html#syntax-mut
172180
text: var
@@ -178,6 +186,7 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df
178186
text: 𝗆𝗈𝖽𝗎𝗅𝖾; url: exec/runtime.html#syntax-frame
179187
text: 𝗆𝖾𝗆𝖺𝖽𝖽𝗋𝗌; url: exec/runtime.html#syntax-moduleinst
180188
text: sequence; url: syntax/conventions.html#grammar-notation
189+
text: exception; for: eventtype/attribute; url: syntax/types.html#syntax-eventtype
181190
urlPrefix: https://heycam.github.io/webidl/; spec: WebIDL
182191
type: dfn
183192
text: create a namespace object; url: create-a-namespace-object
@@ -382,12 +391,18 @@ A {{Module}} object represents a single WebAssembly module. Each {{Module}} obje
382391
1. Note: [=module_instantiate=] invoked below will check the imported {{Memory}}'s size against the importing module's requirements.
383392
1. Let |externmem| be the [=external value=] [=external value|𝗆𝖾𝗆=] |v|.\[[Memory]].
384393
1. [=Append=] |externmem| to |imports|.
385-
1. Otherwise, |externtype| is of the form [=𝗍𝖺𝖻𝗅𝖾=] <var ignore>tabletype</var>,
394+
1. If |externtype| is of the form [=𝗍𝖺𝖻𝗅𝖾=] <var ignore>tabletype</var>,
386395
1. If |v| is not a {{Table}} instance, throw a {{LinkError}} exception.
387396
1. Note: The table's length, etc. is checked by [=module_instantiate=] invoked below.
388397
1. Let |tableaddr| be |v|.\[[Table]]
389398
1. Let |externtable| be the [=external value=] [=external value|𝗍𝖺𝖻𝗅𝖾=] |tableaddr|.
390399
1. [=Append=] |externtable| to |imports|.
400+
1. If |externtype| is of the form [=externtype/event=] |attribute| <var ignore>functype</var>,
401+
1. Assert: |attribute| is [=eventtype/attribute/exception=].
402+
1. If |v| does not [=implement=] {{Exception}}, throw a {{LinkError}} exception.
403+
1. Let |tag| be |v|'s [=Exception/exception tag=].
404+
1. Let |extern| be the [=external value=] [=external value/event=] |tag|.
405+
1. [=Append=] |extern| to |imports|.
391406
1. Return |imports|.
392407
</div>
393408

@@ -412,11 +427,17 @@ A {{Module}} object represents a single WebAssembly module. Each {{Module}} obje
412427
1. Let [=external value|𝗆𝖾𝗆=] |memaddr| be |externval|.
413428
1. Let |memory| be [=create a memory object|a new Memory object=] created from |memaddr|.
414429
1. Let |value| be |memory|.
415-
1. Otherwise, |externtype| is of the form [=𝗍𝖺𝖻𝗅𝖾=] <var ignore>tabletype</var>,
430+
1. If |externtype| is of the form [=𝗍𝖺𝖻𝗅𝖾=] <var ignore>tabletype</var>,
416431
1. Assert: |externval| is of the form [=external value|𝗍𝖺𝖻𝗅𝖾=] |tableaddr|.
417432
1. Let [=external value|𝗍𝖺𝖻𝗅𝖾=] |tableaddr| be |externval|.
418433
1. Let |table| be [=create a Table object|a new Table object=] created from |tableaddr|.
419434
1. Let |value| be |table|.
435+
1. If |externtype| is of the form [=externtype/event=] |attribute| <var ignore>functype</var>,
436+
1. Assert: |attribute| is [=eventtype/attribute/exception=].
437+
1. Assert: |externval| is of the form [=external value/event=] |eventaddr|.
438+
1. Let [=external value/event=] |eventaddr| be |externval|.
439+
1. Let |exception| be [=create an Exception object|a new Exception object=] created from |eventaddr|.
440+
1. Let |value| be |exception|.
420441
1. Let |status| be ! [=CreateDataProperty=](|exportsObject|, |name|, |value|).
421442
1. Assert: |status| is true.
422443

@@ -508,7 +529,8 @@ enum ImportExportKind {
508529
"function",
509530
"table",
510531
"memory",
511-
"global"
532+
"global",
533+
"event"
512534
};
513535

514536
dictionary ModuleExportDescriptor {
@@ -537,6 +559,7 @@ interface Module {
537559
* "table" if |type| is of the form [=𝗍𝖺𝖻𝗅𝖾=] tabletype
538560
* "memory" if |type| is of the form [=𝗆𝖾𝗆=] memtype
539561
* "global" if |type| is of the form [=𝗀𝗅𝗈𝖻𝖺𝗅=] globaltype
562+
* "event" if |type| is of the form [=externtype/event=] <var ignore>event</var>
540563
</div>
541564

542565
<div algorithm>
@@ -1003,14 +1026,8 @@ This slot holds a [=function address=] relative to the [=surrounding agent=]'s [
10031026
1. Let (|store|, |ret|) be the result of [=func_invoke=](|store|, |funcaddr|, |argsSeq|).
10041027
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
10051028
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>.
1006-
1. If |ret| is exception [=exnref=] |exception|,
1007-
1. If |exception|'s [=exnref/exception tag=] is the [=JavaScript exception tag=], then
1008-
1. Let [=ref.extern=] |externaddr| be |exception|'s [=exnref/payload=].
1009-
1. Let |jsException| be the result of [=retrieving an extern value=] from |externaddr|.
1010-
1. Throw |jsException|.
1011-
1. Throw a {{RuntimeError}} exception.
1012-
1013-
Issue: Probably shouldn't be a {{RuntimeError}}.
1029+
1. If |ret| is exception |exnaddr|,
1030+
1. Throw [=ToJSValue=]([=ref.exn=] |exnaddr|).
10141031
1. If |ret| is empty, return undefined.
10151032
1. Otherwise, return [=ToJSValue=](|v|), where |v| is the singular element of |ret|.
10161033
</div>
@@ -1041,7 +1058,7 @@ Note: Exported Functions do not have a \[[Construct]] method and thus it is not
10411058
1. Let |result| be the result of [=run a host function|running a host function=] from |func|, |functype|, and |arguments|.
10421059
1. Assert: |result|.\[[Type]] is <emu-const>throw</emu-const> or <emu-const>return</emu-const>.
10431060
1. If |result|.\[[Type]] is <emu-const>throw</emu-const>, then:
1044-
1. Let |exception| be [=ToWebAssemblyValue=](|result|.\[[Value]], [=anyref=]).
1061+
1. Let |exception| be [=ToWebAssemblyValue=](|result|.\[[Value]], [=exnref=]).
10451062
1. [=WebAssembly/Throw=] |exception| with the [=JavaScript exception tag=].
10461063
1. Otherwise, return |result|.\[[Value]].
10471064
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
@@ -1060,6 +1077,11 @@ The algorithm <dfn>ToJSValue</dfn>(|w|) coerces a [=WebAssembly value=] to a Jav
10601077
1. If |w| is of the form [=ref.null=], return null.
10611078
1. If |w| is of the form [=ref.func=] |funcaddr|, return the result of creating [=a new Exported Function=] from |funcaddr|.
10621079
1. If |w| is of the form [=ref.host=] |hostaddr|, return the result of [=retrieving a host value=] from |hostaddr|.
1080+
1. If |w| is of the form [=ref.exn=] |exntag| |payload|, then
1081+
1. If |exntag| is the [=JavaScript exception tag=], then
1082+
1. Let « [=ref.extern=] |externaddr| » be |payload|.
1083+
1. Return the result of [=retrieving an extern value=] from |externaddr|.
1084+
1. Return a {{RuntimeException}} whose [=RuntimeException/internal exception=] is |exnaddr|.
10631085

10641086
<!-- If the WebAssembly value is optional, then given `None`, return JavaScript value `undefined`. -->
10651087

@@ -1087,6 +1109,15 @@ The algorithm <dfn>ToWebAssemblyValue</dfn>(|v|, |type|, |error|) coerces a Java
10871109
1. If |type| is [=𝖿𝟨𝟦=],
10881110
1. Let |f64| be ? [=ToNumber=](|v|).
10891111
1. Return [=𝖿𝟨𝟦.𝖼𝗈𝗇𝗌𝗍=] |f64|.
1112+
1. If |type| is [=exnref=],
1113+
1. If |v| [=implements=] {{RuntimeException}},
1114+
1. Let |exnaddr| be |v|'s [=RuntimeException/internal exception=].
1115+
1. Otherwise,
1116+
1. Let |payload| be [=ToWebAssemblyValue=](|v|, [=anyref=]).
1117+
1. Let |exnaddr| be a new [=event address=] referencing |payload| and the [=JavaScript exception tag=].
1118+
1. Return [=ref.exn=] |exnaddr|.
1119+
1120+
Note: There is no way to compare [=exnref=] values by reference.
10901121
1. Assert: |type| is a reference type.
10911122
1. If |type| is [=anyref=],
10921123
1. Do nothing.
@@ -1116,22 +1147,85 @@ The algorithm <dfn>ToWebAssemblyValue</dfn>(|v|, |type|, |error|) coerces a Java
11161147

11171148
<h3 id="exceptions">Exceptions</h3>
11181149

1119-
A new type <dfn>exnref</dfn> is introduced for references to exceptions.
1120-
Values of this type have an <dfn for=exnref>exception tag</dfn> and a <dfn for=exnref>payload</dfn>
1150+
Values of the [=exnref=] type have an <dfn for=exnref>exception tag</dfn> and a
1151+
<dfn for=exnref>payload</dfn>
11211152
(whose type is dependent on the value of the [=exnref/exception tag=]).
11221153
The concrete representation of values of this type is undefined.
11231154

1155+
<h4 id="runtime-exceptions">Exception types</h4>
1156+
1157+
<pre class="idl">
1158+
[LegacyNamespace=WebAssembly, Exposed=(Window,Worker,Worklet)]
1159+
interface Exception {
1160+
};
1161+
</pre>
1162+
1163+
An {{Exception}} value represents a type of exception.
1164+
{{Exception}} values have an <dfn for=Exception>exception tag</dfn>.
1165+
1166+
The <dfn for=Exception>payload types</dfn> of an {{Exception}} is the [=list=] of types of
1167+
1168+
1169+
<h4 id="runtime-exceptions">Runtime exceptions</h4>
1170+
1171+
<pre class="idl">
1172+
[LegacyNamespace=WebAssembly, Exposed=(Window,Worker,Worklet)]
1173+
interface RuntimeException {
1174+
constructor(Exception exceptionType, sequence&lt;any> payload);
1175+
sequence&lt;any> arguments(Exception exceptionType);
1176+
};
1177+
</pre>
1178+
1179+
A {{RuntimeException}} value represents an [=exnref=] value.
1180+
{{RuntimeException}} values have an <dfn for=RuntimeException>internal exception</dfn>, which
1181+
is an [=event address=].
1182+
1183+
Issue: Should it be possible to construct {{RuntimeException}} objects from JavaScript? Only with
1184+
the [=JavaScript exception tag=] or also with others? How?
1185+
<div algorithm>
1186+
1187+
The <dfn constructor for=RuntimeException
1188+
lt="RuntimeException(exceptionType, payload)">new RuntimeException(|exceptionType|, |payload|)</dfn>
1189+
constructor steps are:
1190+
1191+
1. Let |types| be |exceptionType|'s [=Exception/exception tag=]'s [=list=] of types.
1192+
1. If |types|'s [=list/size=] is not |payload|'s [=list/size=],
1193+
1. Throw a {{TypeError}}.
1194+
1. Let |wasmPayload| be « ».
1195+
1. [=list/iterate|For each=] |value| and |resultType| of |payload| and |types|, paired linearly,
1196+
1. [=list/Append=] [=ToWebAssemblyValue=](|value|, |resultType|) to |wasmPayload|.
1197+
1. Let |exception| be a new [=exnref=] with [=exnref/exception tag=] set to |exceptionType|'s
1198+
[=Exception/exception tag=], and [=exnref/payload=] |wasmPayload|.
1199+
1. Set **this**'s [=RuntimeException/internal exception=] to |exception|.
1200+
1201+
</div>
1202+
1203+
<div algorithm>
1204+
1205+
The <dfn method for="RuntimeException">arguments(|exceptionType|)</dfn> method steps are:
1206+
1207+
1. Let |internal| be **this**'s [=RuntimeException/internal exception=].
1208+
1. If |internal|'s [=exnref/exception tag=] is not equal to |exceptionType|'s [=Exception/exception tag=],
1209+
1. Throw a {{TypeError}}.
1210+
1. Let |payload| be |internal|'s [=exnref/payload=].
1211+
1. Let |result| be « ».
1212+
1. [=list/iterate|For each=] |value| of |payload|,
1213+
1. [=list/Append=] [=ToJSValue=](|value|) to |result|.
1214+
1. Return |result|.
1215+
1216+
</div>
1217+
1218+
<h4 id="js-exceptions">JavaScript exceptions</h4>
1219+
11241220
The <dfn>JavaScript exception tag</dfn> is an [=exnref/exception tag=] reserved by this
11251221
specification to distinguish exceptions originating from JavaScript.
11261222

1127-
Issue: Should it be possible for `br_on_exn` to extract the payload from an exception with this tag.
1223+
Issue: Should it be possible for `br_on_exn` to extract the payload from an exception with this tag?
11281224

11291225
<div algorithm>
11301226

1131-
To <dfn for=WebAssembly>throw</dfn> a WebAssembly value |payload| given an [=exception tag=] |tag|,
1132-
perform the following steps:
1227+
To <dfn for=WebAssembly>throw</dfn> an [=exnref=] |exception|, perform the following steps:
11331228

1134-
1. Let |exception| be a new [=exnref=] value with |payload| and |tag|.
11351229
1. Unwind the stack until reaching the *catching try block*.
11361230
1. Push |exception| onto the operand stack.
11371231
1. Transfer control to the catch block.

0 commit comments

Comments
 (0)