Skip to content

[GR-63376] Implement new Wasm Polyglot API. #11558

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Jul 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a26724a
Implemented the new wasm polyglot api.
flohuemer Apr 14, 2025
e1f1aa4
Context#eval now returns a module by default in GraalWasm. Adjusted t…
flohuemer May 13, 2025
992f69e
Fix reading exports; minor code cleanups.
woess Jun 2, 2025
c33597b
Fixes for module.newInstance() with WASI and importObject.
woess Jun 3, 2025
ed1a108
Adapt PolyBenchLauncher to GraalWasm API changes.
woess Jun 3, 2025
204884f
Avoid using contextStore().
woess Jun 16, 2025
31f9564
Refactor ExceptionProvider.
woess Jul 3, 2025
e3875c5
Update jekyll gem to resolve dependency errors on Ruby 3.4.0
woess Jun 3, 2025
36c0366
Add simple wat lexer rouge plugin for syntax highlighting.
woess Jun 3, 2025
bc1e397
Update GraalWasm embedding examples for 25.0 API changes.
woess Jun 3, 2025
6de7dfc
Update Readme for GraalWasm Polyglot API changes.
woess Jun 17, 2025
d5b2e3a
Add GraalWasm Polyglot API migration and usage guide.
woess Jul 1, 2025
1451976
Update GraalWasm changelog.
woess Jul 3, 2025
533d702
Add runInWasmContext utility method to replace __testutil_run_custom_…
woess Jul 9, 2025
afca8c0
Instantiate only the built-in modules that are actually imported.
woess Jul 8, 2025
7011fdb
Adapt tests to not call linkReferences() or newInstance() with module…
woess Jul 8, 2025
d203b2e
Remove WasmInstance.linkReferences().
woess Jul 8, 2025
aefb945
Remove "linkReferences" and "references" members from docs.
woess Jul 8, 2025
1bcadf3
Remove "references" member.
woess Jul 9, 2025
8e1b511
Remove support for instantiating multiple modules at once.
woess Jul 9, 2025
a88f9ff
Fix data segment parsing from runtime bytecode.
woess Jul 9, 2025
90732e1
Fix importing globals from another module instance's exports.
woess Jul 9, 2025
b632e46
Growable global variable arrays should not be compilation-final.
woess Jul 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -591,7 +591,7 @@ public void run() {
// language-specific lookup
switch (languageId) {
case "wasm":
result = evalSourceValue.getMember(memberName);
result = evalSourceValue.newInstance().getMember("exports").getMember(memberName);
break;
case "java":
// Espresso doesn't provide methods as executable values.
Expand Down
19 changes: 19 additions & 0 deletions wasm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@ This changelog summarizes major changes to the WebAssembly engine implemented in

## Version 25.0.0

* BREAKING: Changed Context.eval of _wasm_ sources to return a compiled, but not yet instantiated, module object instead of the module instance.
To instantiate the module, you have to call `newInstance()` on the module object now, e.g.:
```java
Context c = Context.create();
Source wasmSource = Source.newBuilder...;
Value module = c.eval(wasmSource);
Value instance = module.newInstance(); // < 25.0: c.eval(wasmSource)
```
This change enables modules to be instantiated multiple times—and run independently—within the same context. Previously, each module could only be instantiated once per context.
`newInstance()` optionally also accepts an import object, similar to the JS WebAssembly API, as well as other modules to be linked together with the module.
The previous behavior can still be restored with the experimental option `--wasm.EvalReturnsInstance=true`.
Note: Modules instantiated using `module.newInstance()` are not accessible via `context.getBindings("wasm")`, unlike modules instantiated using `context.eval` when using `--wasm.EvalReturnsInstance=true`.
* BREAKING: Exports are no longer exposed as direct members of the module instance.
Use the `exports` member of the module instance to access its exports, e.g:.
```java
Value mainFunction = instance.getMember("exports").getMember("main"); // < 25.0: instance.getMember("main")
```
This aligns with the JS WebAssembly API and allows other members to be introduced on the module instance without potential name clashes.
More information about these API changes and examples can be found in the [GraalWasm Polyglot API Migration Guide](docs/user/GraalWasmAPIMigration.md) and the [Readme](docs/user/README.md).
* Implemented support for editing primitive values during debugging. Fixed several debugger-related issues.

## Version 24.2.0
Expand Down
2 changes: 1 addition & 1 deletion wasm/docs/site/Gemfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
source "https://rubygems.org"

gem "jekyll", "~> 4.3.4"
gem "jekyll", "~> 4.4.0"

gem "graal-languages-jekyll-theme"

Expand Down
45 changes: 24 additions & 21 deletions wasm/docs/site/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ GEM
io-event (~> 1.9)
metrics (~> 0.12)
traces (~> 0.15)
base64 (0.3.0)
bigdecimal (3.1.8)
coderay (1.1.3)
colorator (1.1.0)
concurrent-ruby (1.3.4)
concurrent-ruby (1.3.5)
console (1.29.3)
fiber-annotation
fiber-local (~> 1.1)
Expand All @@ -26,17 +27,16 @@ GEM
ethon (0.16.0)
ffi (>= 1.15.0)
eventmachine (1.2.7)
ffi (1.17.0-arm64-darwin)
ffi (1.17.0-x86_64-linux-gnu)
ffi (1.17.0)
fiber-annotation (0.2.0)
fiber-local (1.1.0)
fiber-storage
fiber-storage (1.0.0)
forwardable-extended (2.6.0)
google-protobuf (4.28.3-arm64-darwin)
google-protobuf (4.31.1-arm64-darwin)
bigdecimal
rake (>= 13)
google-protobuf (4.28.3-x86_64-linux)
google-protobuf (4.31.1-x86_64-linux-gnu)
bigdecimal
rake (>= 13)
graal-languages-jekyll-theme (0.1.0)
Expand All @@ -56,36 +56,39 @@ GEM
csv
mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2)
i18n (1.14.6)
i18n (1.14.7)
concurrent-ruby (~> 1.0)
io-event (1.9.0)
jekyll (4.3.4)
jekyll (4.4.1)
addressable (~> 2.4)
base64 (~> 0.2)
colorator (~> 1.0)
csv (~> 3.0)
em-websocket (~> 0.5)
i18n (~> 1.0)
jekyll-sass-converter (>= 2.0, < 4.0)
jekyll-watch (~> 2.0)
json (~> 2.6)
kramdown (~> 2.3, >= 2.3.1)
kramdown-parser-gfm (~> 1.0)
liquid (~> 4.0)
mercenary (>= 0.3.6, < 0.5)
mercenary (~> 0.3, >= 0.3.6)
pathutil (~> 0.9)
rouge (>= 3.0, < 5.0)
safe_yaml (~> 1.0)
terminal-table (>= 1.8, < 4.0)
webrick (~> 1.7)
jekyll-relative-links (0.7.0)
jekyll (>= 3.3, < 5.0)
jekyll-sass-converter (3.0.0)
sass-embedded (~> 1.54)
jekyll-sass-converter (3.1.0)
sass-embedded (~> 1.75)
jekyll-seo-tag (2.8.0)
jekyll (>= 3.8, < 5.0)
jekyll-watch (2.2.1)
listen (~> 3.0)
json (2.10.1)
kramdown (2.4.0)
rexml
kramdown (2.5.1)
rexml (>= 3.3.9)
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.4)
Expand Down Expand Up @@ -117,18 +120,18 @@ GEM
racc (1.8.1)
rack (3.1.8)
rainbow (3.1.1)
rake (13.2.1)
rake (13.3.0)
rb-fsevent (0.11.2)
rb-inotify (0.11.1)
ffi (~> 1.0)
rexml (3.3.9)
rouge (4.5.1)
rexml (3.4.1)
rouge (4.5.2)
ruby-rc4 (0.1.5)
safe_yaml (1.0.5)
sass-embedded (1.81.0-arm64-darwin)
google-protobuf (~> 4.28)
sass-embedded (1.81.0-x86_64-linux-gnu)
google-protobuf (~> 4.28)
sass-embedded (1.89.1-arm64-darwin)
google-protobuf (~> 4.31)
sass-embedded (1.89.1-x86_64-linux-gnu)
google-protobuf (~> 4.31)
siteleaf (2.3.0)
httparty (>= 0.16.0)
jekyll (>= 1.4.1)
Expand All @@ -141,7 +144,7 @@ GEM
typhoeus (1.4.1)
ethon (>= 0.9.0)
unicode-display_width (2.6.0)
webrick (1.9.0)
webrick (1.9.1)
yell (2.2.2)
zeitwerk (2.7.2)

Expand All @@ -153,7 +156,7 @@ DEPENDENCIES
graal-languages-jekyll-theme
html-proofer
http_parser.rb (~> 0.6.0)
jekyll (~> 4.3.4)
jekyll (~> 4.4.0)
jekyll-relative-links
jekyll-seo-tag
pry
Expand Down
64 changes: 64 additions & 0 deletions wasm/docs/site/_plugins/wat_lexer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl.

require 'rouge'

# overly simplistic wat lexer
module Rouge
module Lexers
class Wat < RegexLexer
tag 'wat'
filenames '*.wat'
title "wat"
desc "WebAssembly Text Format"

state :root do
rule %r/;;.*$/, Comment::Single
rule %r/\(;.*?;\)/m, Comment::Multiline

# literals
rule %r/"([^\\"]|\\.)*?"/, Str
rule %r/[-+]?(?:\d+|0x[0-9a-fA-F]+)/, Num::Integer
rule %r/[-+]?\d+\.\d+(?:[eE][-+]?\d+)?/, Num::Float

# keywords
rule %r/\b(
module|func|type|param|result|local|global|memory|data|table|elem|start|import|export|mut
)(?!\.)\b/x, Keyword

# types
rule %r/\b(
i32|i64|f32|f64|v128|funcref|externref
)(?!\.)\b/x, Keyword::Type

# instructions
rule %r/\b(
local\.(?:get|set|tee)|
global\.(?:get|set)|
(?:i32|i64|f32|f64|v128|i8x16|i16x8|i32x4|i64x2|f32x4|f64x2)\.[a-z0-9_]+|
nop|unreachable|
block|loop|if|else|end|
br|br_if|br_table|
return|
call|call_indirect|
drop|select|
table\.(?:get|set|size|grow|fill|copy|init)|
elem\.drop|
memory\.(?:size|grow|fill|copy|init)
data\.drop|
ref\.(?:null|is_null|func)
)(?!\.)\b/x, Name::Attribute

# names
rule %r/\$[a-zA-Z0-9._-]*/, Name::Builtin

# attributes
rule %r/(?:offset|align)=/, Name::Property

rule %r/[()]/, Punctuation

rule %r/\s+/, Text
end
end
end
end
54 changes: 42 additions & 12 deletions wasm/docs/site/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,15 @@ implementation("org.graalvm.polyglot:wasm:{{ site.language_version }}")
<div class="language__example-subtitle">
<h4>2. Create a WebAssembly module, for example with <a href="https://webassembly.github.io/wabt/demo/wat2wasm/" target="_blank">wat2wasm</a></h4>
</div>
{%- highlight javascript -%}
(module
(func (export "addTwo") (param i32 i32) (result i32)
local.get 0
local.get 1
i32.add))
{%- highlight wat -%}
;; wat2wasm add-two.wat -o add-two.wasm
(module
(func (export "addTwo") (param i32 i32) (result i32)
local.get 0
local.get 1
i32.add
)
)
{%- endhighlight -%}
</div>
<div class="example-logo-box">
Expand All @@ -167,10 +170,34 @@ implementation("org.graalvm.polyglot:wasm:{{ site.language_version }}")
</div>
<div class="languages__example-box">
<div class="languages__snippet">
<div class="language__example-subtitle">
<h4>3. Embed the Wasm module in Java</h4>
</div>
{%- highlight java -%}
<div class="language__example-subtitle">
<h4>3. Embed the Wasm module in Java</h4>
</div>
<div class="tabs-container">
<ul class="nav nav-tabs">
<li><a href="#" data-bs-toggle="tab" data-bs-target="#version25" class="nav-link active">≥ 25.0</a></li>
<li><a href="#" data-bs-toggle="tab" data-bs-target="#version24" class="nav-link">≤ 24.2</a></li>
</ul>
<div class="tab-content">
<div id="version25" class="tab-pane fade show active">
{% highlight java %}
import java.net.URL;

import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;

try (Context context = Context.create()) {
URL wasmFile = Main.class.getResource("add-two.wasm");
Value mainModule = context.eval(Source.newBuilder("wasm", wasmFile).build());
Value mainInstance = mainModule.newInstance();
Value addTwo = mainInstance.getMember("exports").getMember("addTwo");
System.out.println("addTwo(40, 2) = " + addTwo.execute(40, 2));
}
{% endhighlight %}
</div>
<div id="version24" class="tab-pane fade">
{% highlight java %}
import java.net.URL;

import org.graalvm.polyglot.Context;
Expand All @@ -184,8 +211,11 @@ try (Context context = Context.create()) {
Value addTwo = context.getBindings("wasm").getMember(moduleName).getMember("addTwo");
System.out.println("addTwo(40, 2) = " + addTwo.execute(40, 2));
}
{%- endhighlight -%}
</div>
{% endhighlight %}
</div>
</div>
</div>
</div><!-- languages__snippet -->
<div class="example-logo-box">
<img alt="Java icon" src='{{ "/assets/img/logos/java-logo.svg" | relative_url }}' class="languages__example-logo">
</div>
Expand Down
Loading
Loading