WebAssembly/JS-Promise Integration
The WebAssembly JavaScript-Promise Integration Proposal is a proposed extension to the browser JavaScript API: 1 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.
Browser support
There 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:
chrome://flagsSearch for "Experimental WebAssembly JavaScript Promise Integration (JSPI)". Click on the box, select "enable", then restart the browser to enable the feature.
Free Pascal support
Free Pascal support for this extension was merged into the main FPC branch on Jun 26 2023.
Free Pascal language extensions
Suspending externals
Suspending 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:
function compute_delta: double; external 'js' suspending;Or:
function compute_delta: double; external 'js' suspending first;Now we can implement this function asynchronously on the JavaScript side:
var compute_delta = () =>
fetch('https://example.com/data.txt')
.then(res => res.text())
.then(txt => parseFloat(txt));We then prepare the asynchronous function for use as a suspending WebAssembly external, like this:
var suspending_compute_delta = new WebAssembly.Function(
{parameters:[externref],results:['f64']},
compute_delta,
{suspending:"first"}
)We can the use this to form the complete import object:
var importObj = {js: {
compute_delta:suspending_compute_delta}};Note 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. 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:
function compute_delta: double; external 'js' suspending last;And on the JavaScript side, the value of the suspending attribute needs to be changed to: {suspending:"last"}.
Promising exports
In order for calls to suspending functions to work, WebAssembly code execution must be entered via an export, marked as 'promising'. Example:
var
state: double;
function update_state: double;
begin
state := state + compute_delta; // this calls the suspending function 'compute_delta'
update_state := state;
end;
exports
update_state promising;Once again, a promising export has an extra externref parameter automatically added. Here's how it can be wrapper correctly on the JavaScript side:
var sampleModule = WebAssembly.instantiate(demoBuffer,importObj);
var update_state = new WebAssembly.function(
{parameters:[], results:['externref']},
sampleModule.exports.update_state_export,
{promising : "first"})Alternatively, you can use promising last. If you export it like this in Pascal:
exports
update_state promising last;Then you can use {promising : "last"} instead of {promising : "first"} in JavaScript.
See Also
- A working example
- JavaScript-Promise Integration Proposal
- Introducing the WebAssembly JavaScript Promise Integration API
- WebAssembly
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.
Edited on wiki.freepascal.org by 1 person, 2023
From the official wiki's backup of 26 May 2024: who edited this page there, and when. Edits made there after that date were not recorded, and the earlier versions are not shown here; the main page says why.
| When | Who | What changed |
|---|---|---|
| Nickysn | initial version of the page | |
| Nickysn | basic info about the language extension (suspending externals + promising exports) | |
| Nickysn | Added section "browser support" with more info on how to enable this feature | |
| Nickysn | See Also: - added link to the V8 blog | |
| Nickysn | See Also: - added link to the official proposal overview | |
| Nickysn | Suspending externals: - more details on implementing suspending functions on the JavaScript side | |
| Nickysn | Promising exports: - more details on how to use them on the JS side | |
| Nickysn | added link to working example | |
| Nickysn | working example moved to 'see also' section | |
| Nickysn | What's the basic point - calling asynchronous functions as if they are synchronous. | |
| Nickysn | (minor) | |
| Nickysn | Free Pascal support: - branch was merged into main |
Talk about this page
Nobody has opened a bench for this page yet. Sign in to open one.
