mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 1335652 - wasm exceptions part 10: add WebAssembly.RuntimeException r=rhunt
This patch adds the WebAssembly.RuntimeException class in order to represent exceptions thrown from Wasm. When the JS API is finalized, this class may allow access to the thrown values from JS. Differential Revision: https://phabricator.services.mozilla.com/D101134
This commit is contained in:
parent
df9c9cd78c
commit
d8058476ca
@ -122,6 +122,7 @@
|
||||
REAL(WasmTable, OCLASP(WasmTable)) \
|
||||
REAL(WasmGlobal, OCLASP(WasmGlobal)) \
|
||||
REAL(WasmException, OCLASP(WasmException)) \
|
||||
REAL(WasmRuntimeException, OCLASP(WasmRuntimeException)) \
|
||||
REAL(FinalizationRegistry, OCLASP(FinalizationRegistry)) \
|
||||
REAL(WeakRef, OCLASP(WeakRef)) \
|
||||
REAL(Iterator, OCLASP(Iterator)) \
|
||||
|
@ -461,7 +461,7 @@ MSG_DEF(JSMSG_WASM_NONSHARED_WAIT , 0, JSEXN_WASMRUNTIMEERROR, "atomic wait o
|
||||
MSG_DEF(JSMSG_WASM_NULL_REQUIRED, 0, JSEXN_TYPEERR, "nullref requires a null value")
|
||||
MSG_DEF(JSMSG_WASM_SUPPLY_ONLY_ONE, 2, JSEXN_TYPEERR, "exactly one of {0} and {1} must be supplied")
|
||||
MSG_DEF(JSMSG_WASM_MISSING_REQUIRED, 1, JSEXN_TYPEERR, "Missing required argument {0}")
|
||||
MSG_DEF(JSMSG_WASM_EXN_CONSTRUCTOR, 0, JSEXN_WASMRUNTIMEERROR, "cannot call WebAssembly.Exception")
|
||||
MSG_DEF(JSMSG_WASM_EXN_CONSTRUCTOR, 1, JSEXN_WASMRUNTIMEERROR, "cannot call {0}")
|
||||
|
||||
// Proxy
|
||||
MSG_DEF(JSMSG_BAD_TRAP_RETURN_VALUE, 2, JSEXN_TYPEERR,"trap {1} for {0} returned a primitive value")
|
||||
|
@ -129,6 +129,7 @@ enum class GCAbortReason {
|
||||
_(WasmTableTable) \
|
||||
_(WasmExceptionTag) \
|
||||
_(WasmExceptionType) \
|
||||
_(WasmRuntimeExceptionTag) \
|
||||
_(FileObjectFile) \
|
||||
_(Debugger) \
|
||||
_(DebuggerFrameGeneratorInfo) \
|
||||
|
@ -1,13 +1,19 @@
|
||||
// Tests for Wasm exception import and export.
|
||||
|
||||
// The WebAssembly.Exception constructor cannot be called for now until the
|
||||
// JS API specifies the behavior.
|
||||
// JS API specifies the behavior. Same with WebAssembly.RuntimeException.
|
||||
function testException() {
|
||||
assertErrorMessage(
|
||||
() => new WebAssembly.Exception(),
|
||||
WebAssembly.RuntimeError,
|
||||
/cannot call WebAssembly.Exception/
|
||||
);
|
||||
|
||||
assertErrorMessage(
|
||||
() => new WebAssembly.RuntimeException(),
|
||||
WebAssembly.RuntimeError,
|
||||
/cannot call WebAssembly.RuntimeException/
|
||||
);
|
||||
}
|
||||
|
||||
function testImports() {
|
||||
|
@ -157,6 +157,7 @@ bool GlobalObject::skipDeselectedConstructor(JSContext* cx, JSProtoKey key) {
|
||||
case JSProto_WasmTable:
|
||||
case JSProto_WasmGlobal:
|
||||
case JSProto_WasmException:
|
||||
case JSProto_WasmRuntimeException:
|
||||
return false;
|
||||
|
||||
#ifdef JS_HAS_INTL_API
|
||||
|
@ -3391,7 +3391,7 @@ bool WasmExceptionObject::construct(JSContext* cx, unsigned argc, Value* vp) {
|
||||
// here.
|
||||
// For now, we implement the same behavior as V8 and error when called.
|
||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_WASM_EXN_CONSTRUCTOR);
|
||||
JSMSG_WASM_EXN_CONSTRUCTOR, "WebAssembly.Exception");
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -3456,6 +3456,112 @@ ExceptionTag& WasmExceptionObject::tag() const {
|
||||
return *(ExceptionTag*)getReservedSlot(TAG_SLOT).toPrivate();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// WebAssembly.RuntimeException class and methods
|
||||
|
||||
const JSClassOps WasmRuntimeExceptionObject::classOps_ = {
|
||||
nullptr, // addProperty
|
||||
nullptr, // delProperty
|
||||
nullptr, // enumerate
|
||||
nullptr, // newEnumerate
|
||||
nullptr, // resolve
|
||||
nullptr, // mayResolve
|
||||
WasmRuntimeExceptionObject::finalize, // finalize
|
||||
nullptr, // call
|
||||
nullptr, // hasInstance
|
||||
nullptr, // construct
|
||||
nullptr, // trace
|
||||
};
|
||||
|
||||
const JSClass WasmRuntimeExceptionObject::class_ = {
|
||||
"WebAssembly.RuntimeException",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(WasmRuntimeExceptionObject::RESERVED_SLOTS) |
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_FOREGROUND_FINALIZE,
|
||||
&WasmRuntimeExceptionObject::classOps_,
|
||||
&WasmRuntimeExceptionObject::classSpec_};
|
||||
|
||||
const JSClass& WasmRuntimeExceptionObject::protoClass_ = PlainObject::class_;
|
||||
|
||||
static constexpr char WasmRuntimeExceptionName[] = "RuntimeException";
|
||||
|
||||
const ClassSpec WasmRuntimeExceptionObject::classSpec_ = {
|
||||
CreateWasmConstructor<WasmRuntimeExceptionObject, WasmRuntimeExceptionName>,
|
||||
GenericCreatePrototype<WasmRuntimeExceptionObject>,
|
||||
WasmRuntimeExceptionObject::static_methods,
|
||||
nullptr,
|
||||
WasmRuntimeExceptionObject::methods,
|
||||
WasmRuntimeExceptionObject::properties,
|
||||
nullptr,
|
||||
ClassSpec::DontDefineConstructor};
|
||||
|
||||
/* static */
|
||||
void WasmRuntimeExceptionObject::finalize(JSFreeOp* fop, JSObject* obj) {
|
||||
WasmRuntimeExceptionObject& exnObj = obj->as<WasmRuntimeExceptionObject>();
|
||||
if (!exnObj.isNewborn()) {
|
||||
fop->release(obj, &exnObj.tag(), MemoryUse::WasmRuntimeExceptionTag);
|
||||
}
|
||||
}
|
||||
|
||||
bool WasmRuntimeExceptionObject::construct(JSContext* cx, unsigned argc,
|
||||
Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (!ThrowIfNotConstructing(cx, args, "RuntimeException")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: When the JS API is finalized, it may be possible to construct
|
||||
// WebAssembly.RuntimeException instances from JS, but not for now.
|
||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_WASM_EXN_CONSTRUCTOR,
|
||||
"WebAssembly.RuntimeException");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */
|
||||
WasmRuntimeExceptionObject* WasmRuntimeExceptionObject::create(
|
||||
JSContext* cx, wasm::SharedExceptionTag tag,
|
||||
HandleArrayBufferObject values) {
|
||||
RootedObject proto(
|
||||
cx, &cx->global()->getPrototype(JSProto_WasmRuntimeException).toObject());
|
||||
|
||||
AutoSetNewObjectMetadata metadata(cx);
|
||||
RootedWasmRuntimeExceptionObject obj(
|
||||
cx, NewObjectWithGivenProto<WasmRuntimeExceptionObject>(cx, proto));
|
||||
if (!obj) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(obj->isNewborn());
|
||||
InitReservedSlot(obj, TAG_SLOT, tag.forget().take(),
|
||||
MemoryUse::WasmRuntimeExceptionTag);
|
||||
|
||||
obj->initFixedSlot(VALUES_SLOT, ObjectValue(*values));
|
||||
|
||||
MOZ_ASSERT(!obj->isNewborn());
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool WasmRuntimeExceptionObject::isNewborn() const {
|
||||
MOZ_ASSERT(is<WasmRuntimeExceptionObject>());
|
||||
return getReservedSlot(VALUES_SLOT).isUndefined();
|
||||
}
|
||||
|
||||
const JSPropertySpec WasmRuntimeExceptionObject::properties[] = {
|
||||
JS_STRING_SYM_PS(toStringTag, "WebAssembly.RuntimeException",
|
||||
JSPROP_READONLY),
|
||||
JS_PS_END};
|
||||
|
||||
const JSFunctionSpec WasmRuntimeExceptionObject::methods[] = {JS_FS_END};
|
||||
|
||||
const JSFunctionSpec WasmRuntimeExceptionObject::static_methods[] = {JS_FS_END};
|
||||
|
||||
ExceptionTag& WasmRuntimeExceptionObject::tag() const {
|
||||
return *(ExceptionTag*)getReservedSlot(TAG_SLOT).toPrivate();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// WebAssembly class and static methods
|
||||
|
||||
@ -4435,6 +4541,7 @@ static bool WebAssemblyClassFinish(JSContext* cx, HandleObject object,
|
||||
{"Global", JSProto_WasmGlobal},
|
||||
#ifdef ENABLE_WASM_EXCEPTIONS
|
||||
{"Exception", JSProto_WasmException},
|
||||
{"RuntimeException", JSProto_WasmRuntimeException},
|
||||
#endif
|
||||
{"CompileError", GetExceptionProtoKey(JSEXN_WASMCOMPILEERROR)},
|
||||
{"LinkError", GetExceptionProtoKey(JSEXN_WASMLINKERROR)},
|
||||
|
@ -512,6 +512,40 @@ class WasmExceptionObject : public NativeObject {
|
||||
wasm::ExceptionTag& tag() const;
|
||||
};
|
||||
|
||||
// The class of WebAssembly.RuntimeException. This class is used for
|
||||
// representing exceptions thrown from Wasm in JS. (it is also used as
|
||||
// the internal representation for exceptions in Wasm)
|
||||
|
||||
class WasmRuntimeExceptionObject : public NativeObject {
|
||||
static const unsigned TAG_SLOT = 0;
|
||||
static const unsigned VALUES_SLOT = 1;
|
||||
|
||||
static const JSClassOps classOps_;
|
||||
static const ClassSpec classSpec_;
|
||||
static void finalize(JSFreeOp*, JSObject* obj);
|
||||
static void trace(JSTracer* trc, JSObject* obj);
|
||||
|
||||
public:
|
||||
static const unsigned RESERVED_SLOTS = 2;
|
||||
static const JSClass class_;
|
||||
static const JSClass& protoClass_;
|
||||
static const JSPropertySpec properties[];
|
||||
static const JSFunctionSpec methods[];
|
||||
static const JSFunctionSpec static_methods[];
|
||||
static bool construct(JSContext*, unsigned, Value*);
|
||||
|
||||
static WasmRuntimeExceptionObject* create(JSContext* cx,
|
||||
wasm::SharedExceptionTag tag,
|
||||
Handle<ArrayBufferObject*> values);
|
||||
bool isNewborn() const;
|
||||
|
||||
wasm::ExceptionTag& tag() const;
|
||||
|
||||
static size_t offsetOfValues() {
|
||||
return NativeObject::getFixedSlotOffset(VALUES_SLOT);
|
||||
}
|
||||
};
|
||||
|
||||
// The class of the WebAssembly global namespace object.
|
||||
|
||||
class WasmNamespaceObject : public NativeObject {
|
||||
|
@ -88,6 +88,9 @@ typedef GCVector<WasmExceptionObject*, 0, SystemAllocPolicy>
|
||||
WasmExceptionObjectVector;
|
||||
using RootedWasmExceptionObject = Rooted<WasmExceptionObject*>;
|
||||
|
||||
class WasmRuntimeExceptionObject;
|
||||
using RootedWasmRuntimeExceptionObject = Rooted<WasmRuntimeExceptionObject*>;
|
||||
|
||||
namespace wasm {
|
||||
|
||||
using mozilla::Atomic;
|
||||
|
Loading…
Reference in New Issue
Block a user