Sign in Join
Wiki copytemporary

WebAssembly/JS-Promise Integration: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11The WebAssembly JavaScript-Promise Integration Proposal is a proposed extension to the browser JavaScript API: [1](https://github.com/WebAssembly/js-promise-integration/blob/main/proposals/js-promise-integration/Overview.md) It allows calling asynchronous JavaScript functions from WebAssembly code as if they are synchronous, as well as calling WebAssembly functions asynchronously from JavaScript, even though they are implemented as synchronous.
22
33# Browser support
44
55There is currently experimental support implemented in Chrome, Chromium and Edge. So far, browser support is only implemented on the x86_64 and aarch64 platforms. Minimum Chrome versions that support it are 110.0.5473.0 (macOS) / 110.0.5469.0 (Windows, Android) / 110.0.5478.4 (Linux). As an experimental feature, it is disabled by default. To enable it, go to the URL:
66
7-[`chrome://flags`](chrome://flags)
7+```text
8+chrome://flags
9+```
810
911Search for "Experimental WebAssembly JavaScript Promise Integration (JSPI)". Click on the box, select "enable", then restart the browser to enable the feature.
1012
1113# Free Pascal support
1214
1315Free Pascal support for this extension was merged into the main FPC branch on Jun 26 2023.
1416
1517# Free Pascal language extensions
1618
1719## Suspending externals
1820
1921Suspending externals allows calling JavaScript functions that are run asynchronously on the JavaScript side, even though they are called as if they are synchronous on the WebAssembly side. Example:
2022
21-`function compute_delta: double; external 'js' suspending;`
23+``` pascal
24+function compute_delta: double; external 'js' suspending;
25+```
2226
2327Or:
2428
25-`function compute_delta: double; external 'js' suspending first;`
29+``` pascal
30+function compute_delta: double; external 'js' suspending first;
31+```
2632
2733Now we can implement this function asynchronously on the JavaScript side:
2834
29-`var compute_delta = () => `\
30-`  fetch('`[`https://example.com/data.txt`](https://example.com/data.txt)`')`\
31-`    .then(res => res.text())`\
32-`    .then(txt => parseFloat(txt));`
35+``` pascal
36+var compute_delta = () =>
37+ fetch('https://example.com/data.txt')
38+ .then(res => res.text())
39+ .then(txt => parseFloat(txt));
40+```
3341
3442We then prepare the asynchronous function for use as a suspending WebAssembly external, like this:
3543
36-`var suspending_compute_delta = new WebAssembly.Function(`\
37-`  {parameters:[externref],results:['f64']},`\
38-`  compute_delta,`\
39-`  {suspending:"first"}`\
40-`)`
44+``` pascal
45+var suspending_compute_delta = new WebAssembly.Function(
46+ {parameters:[externref],results:['f64']},
47+ compute_delta,
48+ {suspending:"first"}
49+)
50+```
4151
4252We can the use this to form the complete import object:
4353
44-`var importObj = {js: {`\
45-`    compute_delta:suspending_compute_delta}};`
54+``` pascal
55+var importObj = {js: {
56+ compute_delta:suspending_compute_delta}};
57+```
4658
4759Note the extra *externref* parameter, as well as the extra attribute *{suspending:"first"}*. The extra *externref* parameter is automatically added, when a function is declared 'suspending'. It contains a special suspender object that is used internally by the WebAssembly JavaScript Promise Integration extension. For more details, see the [spec](https://github.com/WebAssembly/js-promise-integration/blob/main/proposals/js-promise-integration/Overview.md#specification). Free Pascal automatically adds the suspender as an extra first parameter for functions that are declared external suspending. There's also an option to add it as a last parameter. In this case, the declaration in Free Pascal needs to be changed to:
4860
49-`function compute_delta: double; external 'js' suspending last;`
61+``` pascal
62+function compute_delta: double; external 'js' suspending last;
63+```
5064
5165And on the JavaScript side, the value of the *suspending* attribute needs to be changed to: *{suspending:"last"}*.
5266
5367## Promising exports
5468
5569In order for calls to suspending functions to work, WebAssembly code execution must be entered via an export, marked as 'promising'. Example:
5670
57-`var`\
58-`  state: double;`\
71+``` pascal
72+var
73+ state: double;
5974
60-`function update_state: double;`\
61-`begin`\
62-`  state := state + compute_delta;  // this calls the suspending function 'compute_delta'`\
63-`  update_state := state;`\
64-`end;`\
75+function update_state: double;
76+begin
77+ state := state + compute_delta; // this calls the suspending function 'compute_delta'
78+ update_state := state;
79+end;
6580
66-`exports`\
67-`  update_state promising;`
81+exports
82+ update_state promising;
83+```
6884
6985Once again, a *promising* export has an extra externref parameter automatically added. Here's how it can be wrapper correctly on the JavaScript side:
7086
71-`var sampleModule = WebAssembly.instantiate(demoBuffer,importObj);`\
72-`var update_state = new WebAssembly.function(`\
73-`  {parameters:[], results:['externref']},`\
74-`  sampleModule.exports.update_state_export,`\
75-`  {promising : "first"})`
87+``` pascal
88+var sampleModule = WebAssembly.instantiate(demoBuffer,importObj);
89+var update_state = new WebAssembly.function(
90+ {parameters:[], results:['externref']},
91+ sampleModule.exports.update_state_export,
92+ {promising : "first"})
93+```
7694
7795Alternatively, you can use *promising last*. If you export it like this in Pascal:
7896
79-`exports`\
80-`  update_state promising last;`
97+```text
98+exports
99+ update_state promising last;
100+```
81101
82102Then you can use *{promising : "last"}* instead of *{promising : "first"}* in JavaScript.
83103
84104# See Also
85105
86106- [A working example](https://www.freepascal.org/~michael/pas2js-demos/jspi/)
87107- [JavaScript-Promise Integration Proposal](https://github.com/WebAssembly/js-promise-integration/blob/main/proposals/js-promise-integration/Overview.md)
88108- [Introducing the WebAssembly JavaScript Promise Integration API](https://v8.dev/blog/jspi)
89109- [[WebAssembly]]
90110
91111---
92112*From the Free Pascal wiki, page "WebAssembly/JS-Promise Integration", as it stood on 2023-06-26 after a change by Nickysn, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
93113Category: WebAssembly

Back to history