You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -385,13 +396,18 @@ A {{Module}} object represents a single WebAssembly module. Each {{Module}} obje
385
396
1. Let |o| be [=?=][$Get$](|importObject|, |moduleName|).
386
397
1. If [=Type=](|o|) is not Object, throw a {{TypeError}} exception.
387
398
1. Let |v| be [=?=][$Get$](|o|, |componentName|).
388
-
1. If |externtype| is of the form [=external-type/func=] |functype|,
389
-
1. If [$IsCallable$](|v|) is false, throw a {{LinkError}} exception.
390
-
1. If |v| has a \[[FunctionAddress]] internal slot, and therefore is an [=Exported Function=],
391
-
1. Let |funcaddr| be the value of |v|'s \[[FunctionAddress]] internal slot.
392
-
1. Otherwise,
393
-
1. [=Create a host function=] from |v| and |functype|, and let |funcaddr| be the result.
394
-
1. Let |index| be the number of external functions in |imports|. This value |index| is known as the <dfn>index of the host function</dfn> |funcaddr|.
399
+
1. If |externtype| is of the form [=func=] |functype|,
400
+
1. If [$IsCallable$](|v|) is true
401
+
1. If |v| has a \[[FunctionAddress]] internal slot, and therefore is an [=Exported Function=],
402
+
1. Let |funcaddr| be the value of |v|'s \[[FunctionAddress]] internal slot.
403
+
1. Otherwise,
404
+
1. [=Create a host function=] from |v| and |functype|, and let |funcaddr| be the result.
405
+
1. Otherwise, if |v| has a \[[wrappedFunction]] insternal slot
406
+
1. Let |func| be the value of |v|'s \[[wrappedFunction]] internal slot.
407
+
1. Assert: [$IsCallable$](|func|) is true
408
+
1. [=Create a suspending function|create a suspending function=] from |func| and |functype|, and let |funcaddr| be the result.
409
+
1. Otherwise, throw a {{LinkError}} exception.
410
+
1. Let |index| be the number of external functions in |imports|. This value |index| is known as the <dfn>index of the host function</dfn> |funcaddr|.
395
411
1. Let |externfunc| be the [=external value=][=external value|func=] |funcaddr|.
396
412
1. [=list/Append=] |externfunc| to |imports|.
397
413
1. If |externtype| is of the form [=external-type/global=]<var ignore>mut</var> |valtype|,
@@ -408,6 +424,10 @@ A {{Module}} object represents a single WebAssembly module. Each {{Module}} obje
408
424
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
409
425
1. Let (|store|, |globaladdr|) be [=global_alloc=](|store|, [=const=] |valtype|, |value|).
410
426
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
427
+
1. Otherwise, if |v| [=implements=]{{Global}},
428
+
1. Let |globaladdr| be |v|.\[[Global]].
429
+
1. Otherwise,
430
+
1. Throw a {{LinkError}} exception.
411
431
1. Let |externglobal| be [=external value|global=] |globaladdr|.
412
432
1. [=list/Append=] |externglobal| to |imports|.
413
433
1. If |externtype| is of the form [=external-type/mem=]<var ignore>memtype</var>,
@@ -1126,12 +1146,9 @@ This slot holds a [=function address=] relative to the [=surrounding agent=]'s [
1126
1146
</div>
1127
1147
1128
1148
<div algorithm>
1129
-
To <dfn>call an Exported Function</dfn> with [=function address=] |funcaddr| and a [=list=] of JavaScript arguments |argValues|, perform the following steps:
1130
-
1131
-
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1132
-
1. Let |functype| be [=func_type=](|store|, |funcaddr|).
1149
+
To <dfn>coerce JavaScript arguments</dfn> from a |functype| and a [=list=] of JavaScript arguments |argValues|, perform the following steps
1133
1150
1. Let [|parameters|] → [|results|] be |functype|.
1134
-
1. If |parameters| or |results| contain [=v128=] or [=exnref=], throw a {{TypeError}}.
1151
+
1. If |parameters| or |results| contain [=v128=], throw a {{TypeError}}.
1135
1152
1136
1153
Note: the above error is thrown each time the \[[Call]] method is invoked.
1137
1154
1. Let |args| be « ».
@@ -1141,6 +1158,14 @@ This slot holds a [=function address=] relative to the [=surrounding agent=]'s [
1141
1158
1. Otherwise, let |arg| be undefined.
1142
1159
1. [=list/Append=][=ToWebAssemblyValue=](|arg|, |t|) to |args|.
1143
1160
1. Set |i| to |i| + 1.
1161
+
1. return |args|
1162
+
</div>
1163
+
1164
+
<div algorithm>
1165
+
To <dfn>call an Exported Function</dfn> with [=function address=] |funcaddr| and a [=list=] of JavaScript arguments |argValues|, perform the following steps:
1166
+
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1167
+
1. Let |functype| be [=func_type=](|store|, |funcaddr|).
1168
+
1. Let |args| be the result of [=coerce JavaScript arguments|coercing arguments=] (|functype|,|argValues|)
1144
1169
1. Let (|store|, |ret|) be the result of [=func_invoke=](|store|, |funcaddr|, |args|).
1145
1170
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
1146
1171
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>.
@@ -1169,13 +1194,23 @@ Note: Exported Functions do not have a \[[Construct]] method and thus it is not
1169
1194
1170
1195
<div algorithm>
1171
1196
To <dfn>run a host function</dfn> from the JavaScript object |func|, type |functype|, and [=list=] of [=WebAssembly values=] |arguments|, perform the following steps:
1197
+
1. Let [|parameters|] → [|resultTypes|] be |functype|.
1198
+
1. Let |jsArguments| be the result of [=coerce WebAssembly arguments=](|parameters|,|arguments|)
1199
+
1. Let |ret| be [=?=][$Call$](|func|, undefined, |jsArguments|).
1200
+
1. Return the result of performing [=coerce a JavaScript return=] on |resultTypes| and |ret|.
1201
+
</div>
1172
1202
1173
-
1. Let [|parameters|] → [|results|] be |functype|.
1174
-
1. If |parameters| or |results| contain [=v128=] or [=exnref=], throw a {{TypeError}}.
1203
+
<div algorithm>
1204
+
To <dfn>coerce WebAssembly arguments</dfn> from a [=list=] of |parameterTypes| and a [=list=] of JavaScript arguments |arguments|, perform the following steps
1205
+
1. If |parameterTypes| contain [=v128=], throw a {{TypeError}}.
1175
1206
1. Let |jsArguments| be « ».
1176
1207
1. [=list/iterate|For each=] |arg| of |arguments|,
1177
1208
1. [=list/Append=][=!=][=ToJSValue=](|arg|) to |jsArguments|.
1178
-
1. Let |ret| be [=?=][$Call$](|func|, undefined, |jsArguments|).
1209
+
1. Return |jsArguments|
1210
+
</div>
1211
+
1212
+
<div algorithm>
1213
+
To <dfn>coerce a JavaScript return</dfn> from a JavaScript |ret| and a list of |results| types, perform the following steps:
1179
1214
1. Let |resultsSize| be |results|'s [=list/size=].
1180
1215
1. If |resultsSize| is 0, return « ».
1181
1216
1. Otherwise, if |resultsSize| is 1, return « [=?=][=ToWebAssemblyValue=](|ret|, |results|[0]) ».
@@ -1190,6 +1225,18 @@ Note: Exported Functions do not have a \[[Construct]] method and thus it is not
1190
1225
1. Return |wasmValues|.
1191
1226
</div>
1192
1227
1228
+
<div algorithm>
1229
+
To <dfn>coerce a JavaScript exception</dfn> from a JavaScript exception |v|, perform the following steps:
1230
+
1. If |v| [=implements=]{{Exception}},
1231
+
1. Let |type| be |v|.\[[Type]].
1232
+
1. Let |payload| be |v|.\[[Payload]].
1233
+
1. Otherwise,
1234
+
1. Let |type| be the [=JavaScript exception tag=].
1235
+
1. Let |payload| be « ».
1236
+
1. Let |opaqueData| be [=ToWebAssemblyValue=](|v|, [=externref=])
1237
+
1. Return the triple |type|, |payload| and |opaqueData|.
1238
+
</div>
1239
+
1193
1240
<div algorithm>
1194
1241
To <dfn>create a host function</dfn> from the JavaScript object |func| and type |functype|, perform the following steps:
1195
1242
@@ -1329,6 +1376,154 @@ The algorithm <dfn>ToWebAssemblyValue</dfn>(|v|, |type|) coerces a JavaScript va
1329
1376
1330
1377
</div>
1331
1378
1379
+
<h3 id="jspi">JavaScript Promise Integration</h3>
1380
+
1381
+
A {{Suspending}} object represents a JavaScript function whose calls via WebAssembly imports should be *suspended* when they return a Promise object.
1382
+
Each {{Suspending}} object has a \[[wrappedFunction]] internal slot which holds a JavaScript function.
1383
+
1384
+
In addition, the {{promising}} function takes as argument a WebAssembly function and returns a JavaScript function that returns a Promise that is resolved when the WebAssembly function completes.
1385
+
1386
+
<pre class="idl">
1387
+
[Exposed=*]
1388
+
partial namespace WebAssembly {
1389
+
Function promising(Function wasmFunc);
1390
+
};
1391
+
1392
+
[LegacyNamespace=WebAssembly, Exposed=*]
1393
+
interface Suspending {
1394
+
constructor(Function jsFun);
1395
+
};
1396
+
</pre>
1397
+
1398
+
<div algorithm>
1399
+
The <dfn method for="WebAssembly">promising(|wasmFunc|)</dfn> function, when invoked, performs the following steps:
1400
+
1. If [$IsCallable$](|wasmFunc|) is false, throw a {{TypeError}}.
1401
+
1. If |wasmFunc| does not have a \[[FunctionAddress]] internal slot, throw a {{TypeError}}.
1402
+
1. Let |builder| be a new [=AbstractClosure=] with parameters that captures |wasmFunc| that, when invoked, performs [=run a Promising function=].
The algorithm to <dfn>run a Promising function</dfn> from the JavaScript object |wasmFunc| and a [=list=] of [=WebAssembly values=] |arguments| consists of the following steps:
1408
+
1. Let |promise| be a new [=PromiseCapabilityRecord=].
1409
+
1. Let |funcaddr| be the value of |wasmFunc|'s \[[FunctionAddress]] internal slot.
1410
+
1. Let |runner| be a new [=AbstractClosure=] of no arguments that captures |promise|, |funcaddr|, |arguments| that, when invoked, performs the following steps:
1411
+
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1412
+
1. Let |functype| be [=func_type=](|store|, |funcaddr|).
1413
+
1. Let |args| be the result of [=coerce JavaScript arguments|coercing arguments=] (|functype|,|arguments|)
1414
+
1. Let (|store|, |result|) be the result of [=func_invoke=](|store|, |funcaddr|, |args|).
1415
+
1. Assert: if control reaches here, we have done waiting for suspended imports
1416
+
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
1417
+
1. If |result| 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>.
1418
+
1. Otherwise, if |result| is of the form [=throw=] exnaddr,
1. Let |con| be [=CreateBuiltinFunction=](|runner|,0,"",<<>>)
1433
+
1. Perform [$Call$](|con|, undefined, <<>>)
1434
+
1. Returns |promise|
1435
+
</div>
1436
+
1437
+
Note: The extra |$Call$| in the above algorithm ensures that the creation of the Promise is separated from the fullfilling of that Promise. In effect, this allows suspension of the fullfillment to occur whilst allowing the creation of the Promise itself to continue.
1438
+
1439
+
<div algorithm>
1440
+
The <dfn constructor for="Suspending">Suspending(|jsFun|)</dfn> constructor, when invoked, performs the following steps:
1441
+
1. If [$IsCallable$](|jsFun|) is false, throw a {{TypeError}}.
1442
+
1. Let |suspendingProto| be \[[%WebAssembly.Suspending.prototype%]]
1443
+
1. Let |susp| be the result of [$OrdinaryObjectCreate$](|suspendingProto|)
1444
+
1. Assign the \[[wrappedFunction]] internal slot of |susp| to |jsFun|
1445
+
1. Return |susp|
1446
+
</div>
1447
+
1448
+
<div algorithm>
1449
+
To <dfn>create a suspending function</dfn> from a JavaScript function |func|, with type |functype| perform the following steps:
1450
+
1451
+
1. Assert: [$IsCallable$](|func|).
1452
+
1. Let |stored settings| be the <a spec=HTML>incumbent settings object</a>.
1453
+
1. Let |hostfunc| be a [=host function=] which performs the following steps when called with arguments |arguments|:
1454
+
1. Let |realm| be |func|'s [=associated Realm=].
1455
+
1. Let |relevant settings| be |realm|'s [=realm/settings object=].
1456
+
1. Let |async_context| be the [=surrounding agent=]'s [=running execution context=].
1457
+
1. [=Prepare to run script=] with |relevant settings|.
1458
+
1. [=Prepare to run a callback=] with |stored settings|.
1459
+
1. Let [|parameters|] → [|results|] be |functype|.
1460
+
1. Let |jsArguments| be the result of [=coerce WebAssembly arguments=](|parameters|,|arguments|)
1461
+
1. Let |ret| be [=?=][$Call$](|func|, undefined, |jsArguments|).
1462
+
1. [=Clean up after running a callback=] with |stored settings|.
1463
+
1. [=Clean up after running script=] with |relevant settings|.
1464
+
1. Assert: |ret|.\[[Type]] is <emu-const>throw</emu-const> or <emu-const>normal</emu-const>.
1465
+
1. If |ret|.\[[Type]] is <emu-const>throw</emu-const>, then:
1466
+
1. Let |type|, |payload| and |opaqueData| be the result of [=coerce a JavaScript exception|coercing the JavaScript exception=] |ret|.\[[Value]].
1467
+
1. [=WebAssembly/Throw=] with |type|, |payload| and |opaqueData|.
1468
+
1. Otherwise, if [=list/size=] of |ret| is 1 and [$IsPromise$](|ret|.\[[Value]][0]):
1469
+
1. Let |promise| be |ret|.\[[Value]][0].
1470
+
1. Perform the [=Pause=] procedure, returning a new continuation |k|.
1471
+
1. Let |resolved| be an [=AbstractClosure=] with parameters (|v|) that captures |functype|, |k| and performs the following steps when called:
1472
+
1. Let |resultsSize| be |results|'s [=list/size=].
1473
+
1. If |resultsSize| is not 1, throw a {{TypeError}}.
1474
+
1. Let |resultType| be [|results|].[0].
1475
+
1. Let |returnValue| be [=ToWebAssemblyValue=](|v|, |resultType|).
1476
+
1. Perform the [=Enter=] procedure, passing it the captured continuation |k| the coerced |returnValue| and |async_context|.
1477
+
1. Return undefined.
1478
+
1. Let |onResolved| be [=CreateBuiltinFunction=](|resolved|,1,"",[])
1479
+
1. Let |rejected| be an [=AbstractClosure=] with parameters (|e|) that captures |async_context| and performs the following steps when called:
1480
+
1. Perform the [=Reject=] procedure, passing it the captured continuation |k| the exception value |e| and |async_context|.
1481
+
1. Return undefined.
1482
+
1. Let |onRejected| be [=CreateBuiltinFunction=](|rejected|,1,"",[])
1. Return the result of performing [=coerce a JavaScript return=] on |results| and |ret|.
1486
+
1. Let |store| be the [=surrounding agent=]'s [=associated store=].
1487
+
1. Let (|store|, |funcaddr|) be [=func_alloc=](|store|, |functype|, |hostfunc|).
1488
+
1. Set the [=surrounding agent=]'s [=associated store=] to |store|.
1489
+
1. Return |funcaddr|.
1490
+
</div>
1491
+
1492
+
<div dfn>
1493
+
An [=execution context=] can be marked <dfn>Paused</dfn> to signal that the computation associated with the [=execution context=] has been paused.
1494
+
</div>
1495
+
1496
+
<div algorithm>
1497
+
The <dfn>Pause</dfn> abstract operation takes a currently executing algorithm and pauses it. The most important parameter |ec| of this operation is an
1498
+
[=Execution Context=] which must be the most recent entry in the [=Execution Context Stack=] and which defines which operation is being paused.
1499
+
The result of pausing an operation is a continuation |k| and a newly surfaced [=Execution Context=] -- which must be the [=Execution Context=] immediately
1500
+
beneath the one on the [=Execution Context Stack=] that is [=Paused|paused=].
1501
+
1502
+
1. If |ec| is not the most recent entry on the [=Execution Context Stack=] then trap.
1503
+
1. Let |k| be a continuation that represents the remainder of the computation associated with |ec|.
1504
+
1. Remove |ec| from the [=Execution Context Stack=] and mark it as being [=Paused|paused=].
1505
+
1. Assert that the [=Execution Context Stack=] is not empty.
1506
+
1. Return |k|
1507
+
</div>
1508
+
1509
+
<div algorithm>
1510
+
The <dfn>Enter</dfn> abstract operation takes a continuation object |k|, a value object |v| and an [=execution context=] |ec|, and resumes the operations defined by |k|.
1511
+
1. If |ec| is not marked as [=Paused|paused=] then trap.
1512
+
1. Mark |ec| as not [=Paused|paused=].
1513
+
1. Push |ec| on to the [=Execution Context Stack=], making |ec| the current execution context.
1514
+
1. Resume the operations defined by |k|, passing |v| as the value of the last instruction being performed by |k|
1515
+
1. Return undefined
1516
+
</div>
1517
+
1518
+
<div algorithm>
1519
+
The <dfn>Reject</dfn> abstract operation takes a continuation object |k|, an exception object |e| and an [=execution context=] |ec|, and resumes the operations defined by |k| by throwing an exception to the [=Paused|paused=] computation.
1520
+
1. If |ec| is not marked as [=Paused|paused=] then trap.
1521
+
1. Mark |ec| as not [=Paused|paused=].
1522
+
1. Push |ec| on to the [=Execution Context Stack=], making |ec| the current execution context.
1523
+
1. Let |type|, |payload| and |opaqueData| be the result of performing [=coerce a JavaScript exception=} on |e|
1524
+
1. Resume the operations defined by |k|, performing [=WebAssembly/Throw=] with |type|, |payload| and |opaqueData|.
0 commit comments