Skip to content

Commit c0190bb

Browse files
Automatic merge of master into galahad
2 parents 64d15d9 + 8ad0dc1 commit c0190bb

File tree

7 files changed

+78
-58
lines changed

7 files changed

+78
-58
lines changed

wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/WasmJsApiSuite.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -835,13 +835,11 @@ public void testExportCountsLimit() throws IOException {
835835
context.readModule(binaryWithMixedExports, limits);
836836

837837
final int noLimit = Integer.MAX_VALUE;
838-
limits = new ModuleLimits(noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, 6, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit,
839-
noLimit);
838+
limits = new ModuleLimits(noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, 6, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit);
840839
context.readModule(binaryWithMixedExports, limits);
841840

842841
try {
843-
limits = new ModuleLimits(noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, 5, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit,
844-
noLimit);
842+
limits = new ModuleLimits(noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, 5, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit, noLimit);
845843
context.readModule(binaryWithMixedExports, limits);
846844
Assert.fail("Should have failed - export count exceeds the limit");
847845
} catch (WasmException ex) {

wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/suites/WasmImplementationLimitationsSuite.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -65,7 +65,7 @@ public class WasmImplementationLimitationsSuite {
6565
public static Collection<Object[]> data() {
6666
return Arrays.asList(
6767
stringCase("Table instance - initial size out of bounds",
68-
"table instance size exceeds limit: 2147483648 should be <= 2147483647",
68+
"table instance size exceeds limit: 2147483648 should be <= 10000000",
6969
"(table $table1 2147483648 funcref)", Failure.Type.TRAP),
7070
stringCase("Memory instance - initial size out of bounds",
7171
"memory instance size exceeds limit: 32768 should be <= 32767",

wasm/src/org.graalvm.wasm.test/src/org/graalvm/wasm/test/suites/validation/ValidationSuite.java

+11-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -134,20 +134,23 @@ public static Collection<Object[]> data() {
134134
// checked individually on memories and tables
135135

136136
// ### Function Types
137-
// Return arity
137+
// Return arity limit (implementation-defined)
138+
// Always <= 1 if wasm.MultiValue=false, else constrained by JS API limits
139+
// "maximum number of return values for any function or block is 1,000".
138140
binaryCase(
139141
"Function - cannot return more than one value",
140-
"A function can return at most one result.",
142+
"invalid result arity: 2 should be <= 1",
141143
// (func $f (result i32) i32.const 42 i32.const 42)
142144
"0061 736d 0100 0000 0105 0160 0002 7f03 0201 000a 0801 0600 412a 412a 0b",
143145
Failure.Type.INVALID),
144146

145147
// ### Table types
146-
// Limits
147-
// Limitation only applies to GraalWasm (max array length)
148+
// Table size limit (implementation-defined)
149+
// Constrained by JS API limits, "maximum size of a table is 10,000,000"
150+
// and in GraalWasm, max array length (near 2**31-1).
148151
stringCase(
149152
"Table - initial size out of bounds",
150-
"table instance size exceeds limit: 2147483648 should be <= 2147483647",
153+
"table instance size exceeds limit: 2147483648 should be <= 10000000",
151154
"(table $table1 2147483648 funcref)",
152155
Failure.Type.TRAP),
153156
stringCase(
@@ -359,12 +362,12 @@ public static Collection<Object[]> data() {
359362
// Validated in: BinaryParser#readMemorySection
360363
stringCase(
361364
"Module - two memories (2 locals)",
362-
"A memory has already been declared in the module.",
365+
"multiple memories: 2 should be <= 1",
363366
"(memory $mem1 1) (memory $mem2 1)",
364367
Failure.Type.INVALID),
365368
stringCase(
366369
"Module - two memories (1 local and 1 import)",
367-
"A memory has already been imported in the module.",
370+
"multiple memories: 2 should be <= 1",
368371
"(memory $mem1 (import \"some\" \"memory\") 1) (memory $mem2 1)",
369372
Failure.Type.INVALID),
370373
// Validated in: SymbolTable#validateSingleMemory

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/ModuleLimits.java

+15-19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -52,11 +52,14 @@
5252
* Limits on various aspects of a module.
5353
*/
5454
public final class ModuleLimits {
55+
56+
private static final int SINGLE_MEMORY_COUNT_LIMIT = 1;
57+
private static final int SINGLE_RESULT_COUNT_LIMIT = 1;
58+
5559
private final int moduleSizeLimit;
5660
private final int typeCountLimit;
5761
private final int functionCountLimit;
5862
private final int tableCountLimit;
59-
private final int memoryCountLimit;
6063
private final int multiMemoryCountLimit;
6164
private final int importCountLimit;
6265
private final int exportCountLimit;
@@ -65,32 +68,29 @@ public final class ModuleLimits {
6568
private final int elementSegmentCountLimit;
6669
private final int functionSizeLimit;
6770
private final int paramCountLimit;
68-
private final int resultCountLimit;
6971
private final int multiValueResultCountLimit;
7072
private final int localCountLimit;
7173
private final int tableInstanceSizeLimit;
7274
private final int memoryInstanceSizeLimit;
7375
private final long memory64InstanceSizeLimit;
7476

75-
public ModuleLimits(int moduleSizeLimit, int typeCountLimit, int functionCountLimit, int tableCountLimit, int memoryCountLimit, int multiMemoryCountLimit, int importCountLimit,
77+
public ModuleLimits(int moduleSizeLimit, int typeCountLimit, int functionCountLimit, int tableCountLimit, int memoryCountLimit, int importCountLimit,
7678
int exportCountLimit, int globalCountLimit,
77-
int dataSegmentCountLimit, int elementSegmentCountLimit, int functionSizeLimit, int paramCountLimit, int resultCountLimit, int multiValueResultCountLimit, int localCountLimit,
79+
int dataSegmentCountLimit, int elementSegmentCountLimit, int functionSizeLimit, int paramCountLimit, int resultCountLimit, int localCountLimit,
7880
int tableInstanceSizeLimit, int memoryInstanceSizeLimit, long memory64InstanceSizeLimit) {
7981
this.moduleSizeLimit = minUnsigned(moduleSizeLimit, Integer.MAX_VALUE);
8082
this.typeCountLimit = minUnsigned(typeCountLimit, Integer.MAX_VALUE);
8183
this.functionCountLimit = minUnsigned(functionCountLimit, Integer.MAX_VALUE);
8284
this.tableCountLimit = minUnsigned(tableCountLimit, Integer.MAX_VALUE);
83-
this.memoryCountLimit = minUnsigned(memoryCountLimit, Integer.MAX_VALUE);
84-
this.multiMemoryCountLimit = minUnsigned(multiMemoryCountLimit, Integer.MAX_VALUE);
85+
this.multiMemoryCountLimit = minUnsigned(memoryCountLimit, Integer.MAX_VALUE);
8586
this.importCountLimit = minUnsigned(importCountLimit, Integer.MAX_VALUE);
8687
this.exportCountLimit = minUnsigned(exportCountLimit, Integer.MAX_VALUE);
8788
this.globalCountLimit = minUnsigned(globalCountLimit, Integer.MAX_VALUE);
8889
this.dataSegmentCountLimit = minUnsigned(dataSegmentCountLimit, Integer.MAX_VALUE);
8990
this.elementSegmentCountLimit = minUnsigned(elementSegmentCountLimit, Integer.MAX_VALUE);
9091
this.functionSizeLimit = minUnsigned(functionSizeLimit, Integer.MAX_VALUE);
9192
this.paramCountLimit = minUnsigned(paramCountLimit, Integer.MAX_VALUE);
92-
this.resultCountLimit = minUnsigned(resultCountLimit, Integer.MAX_VALUE);
93-
this.multiValueResultCountLimit = minUnsigned(multiValueResultCountLimit, Integer.MAX_VALUE);
93+
this.multiValueResultCountLimit = minUnsigned(resultCountLimit, Integer.MAX_VALUE);
9494
this.localCountLimit = minUnsigned(localCountLimit, Integer.MAX_VALUE);
9595
this.tableInstanceSizeLimit = minUnsigned(tableInstanceSizeLimit, MAX_TABLE_INSTANCE_SIZE);
9696
this.memoryInstanceSizeLimit = minUnsigned(memoryInstanceSizeLimit, MAX_MEMORY_INSTANCE_SIZE);
@@ -120,8 +120,6 @@ private static long minUnsigned(long a, long b) {
120120
Integer.MAX_VALUE,
121121
Integer.MAX_VALUE,
122122
Integer.MAX_VALUE,
123-
Integer.MAX_VALUE,
124-
Integer.MAX_VALUE,
125123
MAX_TABLE_INSTANCE_SIZE,
126124
MAX_MEMORY_INSTANCE_SIZE,
127125
MAX_MEMORY_64_INSTANCE_SIZE);
@@ -143,11 +141,10 @@ public void checkTableCount(int count) {
143141
}
144142

145143
public void checkMemoryCount(int count, boolean multiMemory) {
146-
if (multiMemory) {
147-
assertUnsignedIntLessOrEqual(count, multiMemoryCountLimit, Failure.MEMORY_COUNT_LIMIT_EXCEEDED);
148-
} else {
149-
assertUnsignedIntLessOrEqual(count, memoryCountLimit, Failure.MEMORY_COUNT_LIMIT_EXCEEDED);
144+
if (!multiMemory) {
145+
assertUnsignedIntLessOrEqual(count, SINGLE_MEMORY_COUNT_LIMIT, Failure.MULTIPLE_MEMORIES);
150146
}
147+
assertUnsignedIntLessOrEqual(count, multiMemoryCountLimit, Failure.MEMORY_COUNT_LIMIT_EXCEEDED);
151148
}
152149

153150
public void checkImportCount(int count) {
@@ -179,11 +176,10 @@ public void checkParamCount(int count) {
179176
}
180177

181178
public void checkResultCount(int count, boolean multiValue) {
182-
if (multiValue) {
183-
assertUnsignedIntLessOrEqual(count, multiValueResultCountLimit, Failure.RESULT_COUNT_LIMIT_EXCEEDED);
184-
} else {
185-
assertUnsignedIntLessOrEqual(count, resultCountLimit, Failure.RESULT_COUNT_LIMIT_EXCEEDED);
179+
if (!multiValue) {
180+
assertUnsignedIntLessOrEqual(count, SINGLE_RESULT_COUNT_LIMIT, Failure.INVALID_RESULT_ARITY);
186181
}
182+
assertUnsignedIntLessOrEqual(count, multiValueResultCountLimit, Failure.RESULT_COUNT_LIMIT_EXCEEDED);
187183
}
188184

189185
public void checkLocalCount(int count) {

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmLanguage.java

+34-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -49,6 +49,7 @@
4949
import org.graalvm.options.OptionValues;
5050
import org.graalvm.wasm.api.JsConstants;
5151
import org.graalvm.wasm.api.WebAssembly;
52+
import org.graalvm.wasm.exception.WasmJsApiException;
5253
import org.graalvm.wasm.memory.WasmMemory;
5354
import org.graalvm.wasm.predefined.BuiltinModule;
5455

@@ -69,19 +70,18 @@
6970
@Registration(id = WasmLanguage.ID, //
7071
name = WasmLanguage.NAME, //
7172
defaultMimeType = WasmLanguage.WASM_MIME_TYPE, //
72-
byteMimeTypes = WasmLanguage.WASM_MIME_TYPE, //
73+
byteMimeTypes = {WasmLanguage.WASM_MIME_TYPE}, //
7374
contextPolicy = TruffleLanguage.ContextPolicy.SHARED, //
7475
fileTypeDetectors = WasmFileDetector.class, //
7576
interactive = false, //
76-
website = "https://www.graalvm.org/")
77+
website = "https://www.graalvm.org/webassembly/")
7778
@ProvidedTags({StandardTags.RootTag.class, StandardTags.RootBodyTag.class, StandardTags.StatementTag.class})
7879
public final class WasmLanguage extends TruffleLanguage<WasmContext> {
7980
public static final String ID = "wasm";
8081
public static final String NAME = "WebAssembly";
8182
public static final String WASM_MIME_TYPE = "application/wasm";
8283
public static final String WASM_SOURCE_NAME_SUFFIX = ".wasm";
83-
public static final String PARSE_JS_MODULE_MARKER = "js_module_decode";
84-
public static final String[] PARSE_JS_MODULE_ARGS = {PARSE_JS_MODULE_MARKER};
84+
public static final String MODULE_DECODE = "module_decode";
8585

8686
private static final LanguageReference<WasmLanguage> REFERENCE = LanguageReference.create(WasmLanguage.class);
8787

@@ -124,10 +124,7 @@ protected CallTarget parse(ParsingRequest request) {
124124
final Source source = request.getSource();
125125
final String moduleName = source.getName();
126126
final byte[] data = source.getBytes().toByteArray();
127-
ModuleLimits moduleLimits = null;
128-
if (!request.getArgumentNames().isEmpty() && PARSE_JS_MODULE_MARKER.equals(request.getArgumentNames().get(0))) {
129-
moduleLimits = JsConstants.JS_LIMITS;
130-
}
127+
ModuleLimits moduleLimits = JsConstants.JS_LIMITS;
131128
final WasmModule module = context.readModule(moduleName, data, moduleLimits);
132129
return new ParsedWasmModuleRootNode(this, module, source).getCallTarget();
133130
}
@@ -142,14 +139,36 @@ private ParsedWasmModuleRootNode(WasmLanguage language, WasmModule module, Sourc
142139
this.source = source;
143140
}
144141

142+
/**
143+
* The CallTarget returned by {@code parse} supports two calling conventions:
144+
*
145+
* <ol>
146+
* <li>(default) zero arguments provided: on the first call, instantiates the decoded module
147+
* and puts it in the context's module instance map; then returns the {@link WasmInstance}.
148+
* <li>first argument is {@code "module_decode"}: returns the decoded {@link WasmModule}
149+
* (i.e. behaves like {@link WebAssembly#moduleDecode module_decode}). Used by the JS API.
150+
* </ol>
151+
*/
145152
@Override
146-
public WasmInstance execute(VirtualFrame frame) {
147-
final WasmContext context = WasmContext.get(this);
148-
WasmInstance instance = context.lookupModuleInstance(module);
149-
if (instance == null) {
150-
instance = context.readInstance(module);
153+
public Object execute(VirtualFrame frame) {
154+
if (frame.getArguments().length == 0) {
155+
final WasmContext context = WasmContext.get(this);
156+
WasmInstance instance = context.lookupModuleInstance(module);
157+
if (instance == null) {
158+
instance = context.readInstance(module);
159+
}
160+
return instance;
161+
} else {
162+
if (frame.getArguments()[0] instanceof String mode) {
163+
if (mode.equals(MODULE_DECODE)) {
164+
return module;
165+
} else {
166+
throw WasmJsApiException.format(WasmJsApiException.Kind.TypeError, "Unsupported first argument: '%s'", mode);
167+
}
168+
} else {
169+
throw WasmJsApiException.format(WasmJsApiException.Kind.TypeError, "First argument must be a string");
170+
}
151171
}
152-
return instance;
153172
}
154173

155174
@Override

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/api/JsConstants.java

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -56,12 +56,10 @@ private JsConstants() {
5656
private static final int GLOBAL_COUNT_LIMIT = 1000000;
5757
private static final int DATA_SEGMENT_LIMIT = 100000;
5858
private static final int TABLE_COUNT_LIMIT = 100000;
59-
private static final int MEMORY_COUNT_LIMIT = 1;
6059
private static final int MULTI_MEMORY_COUNT_LIMIT = 100;
6160
private static final int ELEMENT_SEGMENT_LIMIT = 10000000;
6261
private static final int FUNCTION_SIZE_LIMIT = 7654321;
6362
private static final int PARAM_COUNT_LIMIT = 1000;
64-
private static final int RESULT_COUNT_LIMIT = 1;
6563
private static final int MULTI_VALUE_RESULT_COUNT_LIMIT = 1000;
6664
private static final int LOCAL_COUNT_LIMIT = 50000;
6765
private static final int TABLE_SIZE_LIMIT = 10000000;
@@ -72,7 +70,6 @@ private JsConstants() {
7270
TYPE_COUNT_LIMIT,
7371
FUNCTION_COUNT_LIMIT,
7472
TABLE_COUNT_LIMIT,
75-
MEMORY_COUNT_LIMIT,
7673
MULTI_MEMORY_COUNT_LIMIT,
7774
IMPORT_COUNT_LIMIT,
7875
EXPORT_COUNT_LIMIT,
@@ -81,7 +78,6 @@ private JsConstants() {
8178
ELEMENT_SEGMENT_LIMIT,
8279
FUNCTION_SIZE_LIMIT,
8380
PARAM_COUNT_LIMIT,
84-
RESULT_COUNT_LIMIT,
8581
MULTI_VALUE_RESULT_COUNT_LIMIT,
8682
LOCAL_COUNT_LIMIT,
8783
TABLE_SIZE_LIMIT,

0 commit comments

Comments
 (0)