Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 21 additions & 0 deletions JSTests/wasm/stress/exception-trace-stack-is-error-stack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as assert from "../assert.js";

const tag = new WebAssembly.Tag({ parameters: ["i32"] });

function makeBoth() {
return [new WebAssembly.Exception(tag, [0], { traceStack: true }), new Error()];
}

// Both are created on one line, so only the column of the first frame differs.
const withoutFirstColumn = stack => stack.replace(/:\d+$/m, "");

const [exception, error] = makeBoth();
assert.eq(typeof exception.stack, "string");
assert.eq(withoutFirstColumn(exception.stack), withoutFirstColumn(error.stack));
Comment thread
robobun marked this conversation as resolved.
assert.eq(Object.hasOwn(exception, "stack"), false);

// With no frames an Error has no stack. Interpreter::stackTraceAsString gave "" here.
Error.stackTraceLimit = 0;
const [exceptionWithoutFrames, errorWithoutFrames] = makeBoth();
assert.eq(errorWithoutFrames.stack, undefined);
assert.eq(exceptionWithoutFrames.stack, undefined);
11 changes: 11 additions & 0 deletions Source/JavaScriptCore/wasm/js/WebAssemblyExceptionConstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#if ENABLE(WEBASSEMBLY)

#include "BuiltinNames.h"
#include "ErrorInstanceInlines.h"
#include "Interpreter.h"
#include "IteratorOperations.h"
#include "JITOpaqueByproducts.h"
Expand Down Expand Up @@ -100,10 +101,20 @@ JSC_DEFINE_HOST_FUNCTION(constructJSWebAssemblyException, (JSGlobalObject* globa

auto* exception = JSWebAssemblyException::create(vm, structure, tag->tag(), WTF::move(payload));
if (traceStack) {
#if USE(BUN_JSC_ADDITIONS)
// Take the stack of an Error created here, so that it goes through VM::onComputeErrorInfoJSValue
// like every other stack. Interpreter::stackTraceAsString skips that hook.
constexpr bool useCurrentFrame = false;
auto* error = ErrorInstance::create(vm, globalObject->errorStructure(), String(), JSValue(), nullptr, TypeNothing, ErrorType::Error, useCurrentFrame);
JSValue stack = error->get(globalObject, vm.propertyNames->stack);
RETURN_IF_EXCEPTION(scope, { });
exception->putDirect(vm, vm.propertyNames->builtinNames().stackPrivateName(), stack, static_cast<unsigned>(PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly | PropertyAttribute::DontDelete));
#else
Vector<StackFrame> stackTrace;
constexpr size_t framesToSkip = 1;
vm.interpreter.getStackTrace(exception, stackTrace, framesToSkip, globalObject->stackTraceLimit().value_or(0));
exception->putDirect(vm, vm.propertyNames->builtinNames().stackPrivateName(), jsString(vm, Interpreter::stackTraceAsString(vm, stackTrace)), static_cast<unsigned>(PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly | PropertyAttribute::DontDelete));
#endif
}

return JSValue::encode(exception);
Expand Down
Loading