node/deps/v8/test/mjsunit/wasm/gc-casts-invalid.js
Michaël Zasso 9d7cd9b864
deps: update V8 to 12.8.374.13
PR-URL: https://github.com/nodejs/node/pull/54077
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Richard Lau <rlau@redhat.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
2024-08-16 16:03:01 +02:00

227 lines
7.2 KiB
JavaScript

// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --experimental-wasm-exnref
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
(function TestRefTestInvalid() {
print(arguments.callee.name);
let struct = 0;
let array = 1;
let sig = 2;
let types = [
// source value type |target heap type
[kWasmI32, kAnyRefCode],
[kWasmNullExternRef, struct],
[wasmRefType(struct), kNullFuncRefCode],
[wasmRefType(array), kFuncRefCode],
[wasmRefType(struct), sig],
[wasmRefType(sig), struct],
[wasmRefType(sig), kExternRefCode],
[kWasmAnyRef, kExternRefCode],
[kWasmAnyRef, kFuncRefCode],
[kWasmAnyRef, kExnRefCode],
[wasmRefType(sig), kExnRefCode],
[kWasmNullExternRef, kExnRefCode],
[wasmRefType(array), kNullExnRefCode],
[kWasmNullFuncRef, kNullExnRefCode],
];
let casts = [
kExprRefTest,
kExprRefTestNull,
kExprRefCast,
kExprRefCastNull,
];
for (let [source_type, target_type_imm] of types) {
for (let cast of casts) {
let builder = new WasmModuleBuilder();
assertEquals(struct, builder.addStruct([makeField(kWasmI32, true)]));
assertEquals(array, builder.addArray(kWasmI32));
assertEquals(sig, builder.addType(makeSig([kWasmI32], [])));
builder.addFunction('refTest', makeSig([source_type], []))
.addBody([
kExprLocalGet, 0,
kGCPrefix, cast, target_type_imm,
kExprDrop,
]);
assertThrows(() => builder.instantiate(),
WebAssembly.CompileError,
/has to be in the same reference type hierarchy/);
}
}
})();
(function TestBrOnCastExpectsNonNull() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let struct = builder.addStruct([makeField(kWasmI32, true)]);
builder.addFunction('fct', makeSig([wasmRefNullType(struct)], []))
.addBody([
kExprBlock, kAnyRefCode,
kExprLocalGet, 0,
...wasmBrOnCast(0, wasmRefType(struct), wasmRefType(struct)),
kExprDrop,
kExprReturn,
kExprEnd,
kExprDrop,
kExprReturn,
]);
assertThrows(() => builder.instantiate(),
WebAssembly.CompileError,
/br_on_cast\[0\] expected type \(ref 0\), found local.get of type \(ref null 0\)/);
})();
(function TestBrOnCastExpectsNull() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let struct = builder.addStruct([makeField(kWasmI32, true)]);
builder.addFunction('fct', makeSig([wasmRefType(struct)], []))
.addBody([
kExprBlock, kAnyRefCode,
kExprLocalGet, 0,
...wasmBrOnCast(0, wasmRefNullType(struct), wasmRefNullType(struct)),
kExprDrop,
kExprReturn,
kExprEnd,
kExprDrop,
kExprReturn,
]);
// Specifying a nullable source and providing a non-nullable value is not an
// error (as non-nullable values can be cast implicitly to nullable).
builder.instantiate();
})();
(function TestBrOnCastNonNullToNull() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let struct = builder.addStruct([makeField(kWasmI32, true)]);
builder.addFunction('fct', makeSig([wasmRefType(struct)], []))
.addBody([
kExprBlock, kAnyRefCode,
kExprLocalGet, 0,
...wasmBrOnCast(0, wasmRefType(struct), wasmRefNullType(struct)),
kExprDrop,
kExprReturn,
kExprEnd,
kExprDrop,
kExprReturn,
]);
// Even though the source is non-nullable, if the br_on_cast is set to produce
// a nullable value on cast, the label target must be nullable as well.
assertThrows(() => builder.instantiate(),
WebAssembly.CompileError,
/invalid types for br_on_cast: \(ref null 0\) is not a subtype of \(ref 0\)/);
})();
(function TestBrOnCastInvalidFlags() {
print(arguments.callee.name);
for (let value of [-1, 8, 127, 255, 256]) {
let builder = new WasmModuleBuilder();
let struct = builder.addStruct([makeField(kWasmI32, true)]);
builder.addFunction('fct', makeSig([wasmRefType(struct)], []))
.addBody([
kExprBlock, kAnyRefCode,
kExprLocalGet, 0,
kGCPrefix, kExprBrOnCast,
...wasmUnsignedLeb(value), 0, kAnyRefCode, struct,
kExprDrop,
kExprReturn,
kExprEnd,
kExprDrop,
kExprReturn,
]);
assertThrows(() => builder.instantiate(),
WebAssembly.CompileError,
/invalid br_on_cast flags [0-9]+/);
}
})();
(function TestBrOnCastSourceTypeUpcast() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let struct = builder.addStruct([makeField(kWasmI32, true)]);
builder.addFunction('fct', makeSig([wasmRefType(struct)], []))
.addBody([
kExprBlock, kAnyRefCode,
kExprLocalGet, 0,
...wasmBrOnCast(0, wasmRefType(kWasmAnyRef), wasmRefType(struct)),
kGCPrefix, kExprStructGet, struct, 0,
kExprDrop,
kExprReturn,
kExprEnd,
kExprDrop,
kExprReturn,
]);
// While the value stack type is (ref struct), the source type in the
// br_on_cast is specified as (ref any), so the fallthrough type becomes
// the less specific (ref any).
assertThrows(() => builder.instantiate(),
WebAssembly.CompileError,
/struct.get\[0\] expected type \(ref null 0\), found local.get of type \(ref any\)/);
})();
(function TestBrOnCastFailSourceTypeUpcast() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let struct = builder.addStruct([makeField(kWasmI32, true)]);
let structRefSig =
builder.addType(makeSig([], [wasmRefType(struct)]));
builder.addFunction('fct', makeSig([wasmRefType(struct)], []))
.addBody([
kExprBlock, structRefSig,
kExprLocalGet, 0,
...wasmBrOnCastFail(0, wasmRefNullType(kWasmAnyRef), wasmRefType(struct)),
kExprDrop,
kExprReturn,
kExprEnd,
kExprDrop,
kExprReturn,
]);
// While the value stack type is (ref struct), the source type in the
// br_on_cast_fail is specified as (ref any), so the branch type becomes
// the less specific (ref any).
assertThrows(() => builder.instantiate(),
WebAssembly.CompileError,
/type error in branch\[0\] \(expected \(ref 0\), got anyref\)/);
})();
// Test that validation and code generation works fine in unreachable paths.
(function TestBrOnCastUnreachable() {
print(arguments.callee.name);
let casts = [
wasmBrOnCastFail(
0, wasmRefNullType(kWasmAnyRef), wasmRefNullType(kWasmI31Ref)),
wasmBrOnCast(0, wasmRefNullType(kWasmAnyRef), wasmRefNullType(kWasmI31Ref)),
wasmBrOnCastFail(0, wasmRefNullType(kWasmAnyRef), wasmRefType(kWasmI31Ref)),
wasmBrOnCast(0, wasmRefNullType(kWasmAnyRef), wasmRefType(kWasmI31Ref)),
];
for (let brOnCast of casts) {
let builder = new WasmModuleBuilder();
builder.addFunction(`brOnCastUnreachable`,
makeSig([kWasmExternRef], []))
.addBody([
kExprBlock, kAnyRefCode,
kExprLocalGet, 0,
kGCPrefix, kExprAnyConvertExtern,
kExprUnreachable,
...brOnCast,
kExprReturn,
kExprEnd,
kExprDrop,
]).exportFunc();
let wasm = builder.instantiate().exports;
assertTraps(kTrapUnreachable, () => wasm.brOnCastUnreachable());
}
})();