[wasm][eh] Add WebAssembly.Exception traceStack parameter

Context: https://github.com/WebAssembly/exception-handling/pull/197

This change adds the optional {traceStack: <bool>} parameter to the
WebAssembly.Exception constructor. When set to true, this captures the
stack and sets the `stack` accessor on the exception object.

R=jkummerow@chromium.org

Bug: v8:8091
Change-Id: I4430b6317b27ec62f11e951fbe95ee480ac72d37
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3688402
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81041}
This commit is contained in:
Thibaud Michaud 2022-06-08 16:36:49 +02:00 committed by V8 LUCI CQ
parent 193b82553e
commit cfea0eb0e8
4 changed files with 67 additions and 0 deletions

View File

@ -19,6 +19,7 @@
#include "src/execution/execution.h"
#include "src/execution/frames-inl.h"
#include "src/execution/isolate.h"
#include "src/execution/messages.h"
#include "src/handles/global-handles-inl.h"
#include "src/handles/handles.h"
#include "src/heap/factory.h"
@ -1823,6 +1824,33 @@ void WebAssemblyException(const v8::FunctionCallbackInfo<v8::Value>& args) {
tag_object->serialized_signature(), i_isolate);
EncodeExceptionValues(isolate, signature, args[1], &thrower, values);
if (thrower.error()) return;
// Third argument: optional ExceptionOption ({traceStack: <bool>}).
if (!args[2]->IsNullOrUndefined() && !args[2]->IsObject()) {
thrower.TypeError("Argument 2 is not an object");
return;
}
if (args[2]->IsObject()) {
Local<Context> context = isolate->GetCurrentContext();
Local<Object> trace_stack_obj = Local<Object>::Cast(args[2]);
Local<String> trace_stack_key = v8_str(isolate, "traceStack");
v8::MaybeLocal<v8::Value> maybe_trace_stack =
trace_stack_obj->Get(context, trace_stack_key);
v8::Local<Value> trace_stack_value;
if (maybe_trace_stack.ToLocal(&trace_stack_value) &&
trace_stack_value->BooleanValue(isolate)) {
auto caller = Utils::OpenHandle(*args.NewTarget());
i_isolate->CaptureAndSetErrorStack(runtime_exception, i::SKIP_NONE,
caller);
i::Handle<i::AccessorInfo> error_stack =
i_isolate->factory()->error_stack_accessor();
i::Handle<i::Name> name(i::Name::cast(error_stack->name()), i_isolate);
i::JSObject::SetAccessor(runtime_exception, name, error_stack,
i::DONT_ENUM)
.Assert();
}
}
args.GetReturnValue().Set(
Utils::ToLocal(i::Handle<i::Object>::cast(runtime_exception)));
}

View File

@ -0,0 +1,19 @@
// 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.
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
let builder = new WasmModuleBuilder();
let tag = new WebAssembly.Tag({parameters: []});
let import_index = builder.addImport("m", "throw", kSig_v_v);
builder.addFunction("throw", kSig_v_v)
.addBody([
kExprCallFunction, import_index
]).exportFunc();
function throw_wasm_exn() {
let exception = new WebAssembly.Exception(tag, [], {traceStack: true});
throw exception;
}
let instance = builder.instantiate({"m": {"throw": throw_wasm_exn}});
instance.exports.throw();

View File

@ -0,0 +1,7 @@
*%(basename)s:16: [object WebAssembly.Exception]
throw exception;
^
Error
at throw_wasm_exn (*%(basename)s:15:19)
at throw (wasm://wasm/f232c786:wasm-function[1]:0x32)
at *%(basename)s:19:23

View File

@ -99,6 +99,19 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
assertDoesNotThrow(() => new WebAssembly.Exception(tag, [3, 4, 5n, 6, {}]));
})();
(function TestExceptionStackTrace() {
print(arguments.callee.name);
let tag = new WebAssembly.Tag({parameters: []});
let exn = new WebAssembly.Exception(tag, []);
assertEquals(undefined, exn.stack);
exn = new WebAssembly.Exception(tag, [], {traceStack: false});
assertEquals(undefined, exn.stack);
exn = new WebAssembly.Exception(tag, [], {traceStack: true});
assertTrue(exn.stack.indexOf(arguments.callee.name) > 0);
assertThrows(() => new WebAssembly.Exception(tag, [], 0), TypeError,
/Argument 2 is not an object/);
})();
(function TestCatchJSException() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();