Commit 20ac07ea authored by Thibaud Michaud's avatar Thibaud Michaud Committed by V8 LUCI CQ

[wasm][eh] Add Exception constructor

The WebAssembly.Exception constructor creates a WasmExceptionPackage,
which represents an exception thrown from wasm. The first argument is a
WebAssembly.Tag, and the rest are the values to encode in the exception.

R=jkummerow@chromium.org

Bug: v8:11992
Change-Id: I1327b2e4545159397ffe73a061aa577608167b74
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3049074Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75912}
parent 2db44607
......@@ -1471,6 +1471,36 @@ void WebAssemblyTag(const v8::FunctionCallbackInfo<v8::Value>& args) {
args.GetReturnValue().Set(Utils::ToLocal(exception));
}
void WebAssemblyException(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
HandleScope scope(isolate);
ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Exception()");
if (!args.IsConstructCall()) {
thrower.TypeError("WebAssembly.Exception must be invoked with 'new'");
return;
}
if (!args[0]->IsObject()) {
thrower.TypeError("Argument 0 must be a WebAssembly tag");
return;
}
i::Handle<i::Object> arg0 = Utils::OpenHandle(*args[0]);
if (!i::HeapObject::cast(*arg0).IsWasmExceptionObject()) {
thrower.TypeError("Argument 0 must be a WebAssembly tag");
return;
}
auto tag_object = i::Handle<i::WasmExceptionObject>::cast(arg0);
auto tag = i::Handle<i::WasmExceptionTag>(
i::WasmExceptionTag::cast(tag_object->exception_tag()), i_isolate);
// TODO(thibaudm): Encode arguments in the exception package.
uint32_t size = 0;
i::Handle<i::WasmExceptionPackage> runtime_exception =
i::WasmExceptionPackage::New(i_isolate, tag, size);
args.GetReturnValue().Set(
Utils::ToLocal(i::Handle<i::Object>::cast(runtime_exception)));
}
// WebAssembly.Function
void WebAssemblyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
......@@ -2324,6 +2354,20 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
i::WASM_EXCEPTION_OBJECT_TYPE, WasmExceptionObject::kHeaderSize);
JSFunction::SetInitialMap(isolate, exception_constructor, exception_map,
exception_proto);
// Set up runtime exception constructor.
Handle<JSFunction> runtime_exception_constructor = InstallConstructorFunc(
isolate, webassembly, "Exception", WebAssemblyException);
SetDummyInstanceTemplate(isolate, runtime_exception_constructor);
Handle<Map> initial_map(
isolate->native_context()->wasm_runtime_error_function().initial_map(),
isolate);
Handle<HeapObject> instance_prototype(isolate->native_context()
->wasm_runtime_error_function()
.instance_prototype(),
isolate);
JSFunction::SetInitialMap(isolate, runtime_exception_constructor,
initial_map, instance_prototype);
}
// Setup Function
......
......@@ -298,7 +298,7 @@ ImportedFunctionEntry::ImportedFunctionEntry(
}
// WasmExceptionPackage
OBJECT_CONSTRUCTORS_IMPL(WasmExceptionPackage, JSReceiver)
OBJECT_CONSTRUCTORS_IMPL(WasmExceptionPackage, JSObject)
CAST_ACCESSOR(WasmExceptionPackage)
// WasmExportedFunction
......
......@@ -570,7 +570,7 @@ class WasmExceptionObject
};
// A Wasm exception that has been thrown out of Wasm code.
class V8_EXPORT_PRIVATE WasmExceptionPackage : public JSReceiver {
class V8_EXPORT_PRIVATE WasmExceptionPackage : public JSObject {
public:
static Handle<WasmExceptionPackage> New(
Isolate* isolate, Handle<WasmExceptionTag> exception_tag,
......@@ -587,7 +587,7 @@ class V8_EXPORT_PRIVATE WasmExceptionPackage : public JSReceiver {
static uint32_t GetEncodedSize(const wasm::WasmException* exception);
DECL_CAST(WasmExceptionPackage)
OBJECT_CONSTRUCTORS(WasmExceptionPackage, JSReceiver);
OBJECT_CONSTRUCTORS(WasmExceptionPackage, JSObject);
};
// A Wasm function that is wrapped and exported to JavaScript.
......
......@@ -57,3 +57,33 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
let res = instance.exports.ex;
assertEquals(res, js_ex_i32);
})();
(function TestExceptionConstructor() {
print(arguments.callee.name);
// Check errors.
let js_tag = new WebAssembly.Tag({parameters: []});
assertThrows(() => new WebAssembly.Exception(0), TypeError,
/Argument 0 must be a WebAssembly tag/);
assertThrows(() => new WebAssembly.Exception({}), TypeError,
/Argument 0 must be a WebAssembly tag/);
assertThrows(() => WebAssembly.Exception(js_tag), TypeError,
/WebAssembly.Exception must be invoked with 'new'/);
let js_exception = new WebAssembly.Exception(js_tag);
// Check prototype.
assertSame(WebAssembly.Exception.prototype, js_exception.__proto__);
assertTrue(js_exception instanceof WebAssembly.Exception);
// Check prototype of a thrown exception.
let builder = new WasmModuleBuilder();
let wasm_tag = builder.addException(kSig_v_v);
builder.addFunction("throw", kSig_v_v)
.addBody([kExprThrow, wasm_tag]).exportFunc();
let instance = builder.instantiate();
try {
instance.exports.throw();
} catch (e) {
assertTrue(e instanceof WebAssembly.Exception);
}
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment