зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1717118 - Part 1, rename JS API classes for exceptions r=rhunt
The Wasm exception handling spec has changed to rename "events" to "tags". As a result, `WebAssembly.Exception` gets renamed to `WebAssembly.Tag` and `WebAssembly.RuntimeException` becomes `WebAssembly.Exception`. Differential Revision: https://phabricator.services.mozilla.com/D118281
This commit is contained in:
Родитель
fb077089e7
Коммит
04f64983e2
|
@ -121,8 +121,8 @@
|
|||
REAL(WasmMemory, OCLASP(WasmMemory)) \
|
||||
REAL(WasmTable, OCLASP(WasmTable)) \
|
||||
REAL(WasmGlobal, OCLASP(WasmGlobal)) \
|
||||
REAL(WasmTag, OCLASP(WasmTag)) \
|
||||
REAL(WasmException, OCLASP(WasmException)) \
|
||||
REAL(WasmRuntimeException, OCLASP(WasmRuntimeException)) \
|
||||
REAL(FinalizationRegistry, OCLASP(FinalizationRegistry)) \
|
||||
REAL(WeakRef, OCLASP(WeakRef)) \
|
||||
REAL(Iterator, OCLASP(Iterator)) \
|
||||
|
|
|
@ -422,7 +422,7 @@ MSG_DEF(JSMSG_WASM_COMPILE_ERROR, 1, JSEXN_WASMCOMPILEERROR, "{0}")
|
|||
MSG_DEF(JSMSG_WASM_NO_SHMEM_COMPILE, 0, JSEXN_WASMCOMPILEERROR, "shared memory is disabled")
|
||||
MSG_DEF(JSMSG_WASM_BAD_IMPORT_TYPE, 2, JSEXN_WASMLINKERROR, "import object field '{0}' is not a {1}")
|
||||
MSG_DEF(JSMSG_WASM_BAD_IMPORT_SIG, 2, JSEXN_WASMLINKERROR, "imported function '{0}.{1}' signature mismatch")
|
||||
MSG_DEF(JSMSG_WASM_BAD_EXN_SIG, 2, JSEXN_WASMLINKERROR, "imported exception '{0}.{1}' signature mismatch")
|
||||
MSG_DEF(JSMSG_WASM_BAD_TAG_SIG, 2, JSEXN_WASMLINKERROR, "imported tag '{0}.{1}' signature mismatch")
|
||||
MSG_DEF(JSMSG_WASM_BAD_IMP_INDEX, 1, JSEXN_WASMLINKERROR, "imported {0} with incompatible index type")
|
||||
MSG_DEF(JSMSG_WASM_BAD_IMP_SIZE, 1, JSEXN_WASMLINKERROR, "imported {0} with incompatible size")
|
||||
MSG_DEF(JSMSG_WASM_BAD_IMP_MAX, 1, JSEXN_WASMLINKERROR, "imported {0} with incompatible maximum size")
|
||||
|
|
|
@ -127,9 +127,9 @@ enum class GCAbortReason {
|
|||
_(WasmResolveResponseClosure) \
|
||||
_(WasmModule) \
|
||||
_(WasmTableTable) \
|
||||
_(WasmTagTag) \
|
||||
_(WasmTagType) \
|
||||
_(WasmExceptionTag) \
|
||||
_(WasmExceptionType) \
|
||||
_(WasmRuntimeExceptionTag) \
|
||||
_(WasmRttValueChildren) \
|
||||
_(FileObjectFile) \
|
||||
_(Debugger) \
|
||||
|
|
|
@ -1,19 +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. Same with WebAssembly.RuntimeException.
|
||||
// The WebAssembly.Tag constructor cannot be called for now until the
|
||||
// JS API specifies the behavior. Same with WebAssembly.Exception.
|
||||
function testException() {
|
||||
assertErrorMessage(
|
||||
() => new WebAssembly.Tag(),
|
||||
WebAssembly.RuntimeError,
|
||||
/cannot call WebAssembly.Tag/
|
||||
);
|
||||
|
||||
assertErrorMessage(
|
||||
() => new WebAssembly.Exception(),
|
||||
WebAssembly.RuntimeError,
|
||||
/cannot call WebAssembly.Exception/
|
||||
);
|
||||
|
||||
assertErrorMessage(
|
||||
() => new WebAssembly.RuntimeException(),
|
||||
WebAssembly.RuntimeError,
|
||||
/cannot call WebAssembly.RuntimeException/
|
||||
);
|
||||
}
|
||||
|
||||
function testImports() {
|
||||
|
@ -24,9 +24,9 @@ function testImports() {
|
|||
`;
|
||||
|
||||
assertErrorMessage(
|
||||
() => wasmEvalText(mod, { m: { exn: "not an exception" } }),
|
||||
() => wasmEvalText(mod, { m: { exn: "not a tag" } }),
|
||||
WebAssembly.LinkError,
|
||||
/import object field 'exn' is not a Exception/
|
||||
/import object field 'exn' is not a Tag/
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ function testExports() {
|
|||
`).exports;
|
||||
|
||||
assertEq(typeof exports1.exn, "object");
|
||||
assertEq(exports1.exn instanceof WebAssembly.Exception, true);
|
||||
assertEq(exports1.exn instanceof WebAssembly.Tag, true);
|
||||
|
||||
var exports2 = wasmEvalText(`
|
||||
(module
|
||||
|
@ -45,7 +45,7 @@ function testExports() {
|
|||
`).exports;
|
||||
|
||||
assertEq(typeof exports2.exn, "object");
|
||||
assertEq(exports2.exn instanceof WebAssembly.Exception, true);
|
||||
assertEq(exports2.exn instanceof WebAssembly.Tag, true);
|
||||
}
|
||||
|
||||
function testImportExport() {
|
||||
|
@ -76,7 +76,7 @@ function testImportExport() {
|
|||
);
|
||||
},
|
||||
WebAssembly.LinkError,
|
||||
/imported exception 'm.exn' signature mismatch/
|
||||
/imported tag 'm.exn' signature mismatch/
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ function assertWasmThrowsExn(thunk) {
|
|||
thunk();
|
||||
} catch (exn) {
|
||||
thrown = true;
|
||||
assertEq(exn instanceof WebAssembly.RuntimeException, true);
|
||||
assertEq(exn instanceof WebAssembly.Exception, true);
|
||||
}
|
||||
|
||||
assertEq(thrown, true, "missing exception");
|
||||
|
|
|
@ -158,8 +158,8 @@ bool GlobalObject::skipDeselectedConstructor(JSContext* cx, JSProtoKey key) {
|
|||
case JSProto_WasmMemory:
|
||||
case JSProto_WasmTable:
|
||||
case JSProto_WasmGlobal:
|
||||
case JSProto_WasmTag:
|
||||
case JSProto_WasmException:
|
||||
case JSProto_WasmRuntimeException:
|
||||
return false;
|
||||
|
||||
#ifdef JS_HAS_INTL_API
|
||||
|
|
|
@ -10602,10 +10602,8 @@ bool BaseCompiler::emitCatch() {
|
|||
RegRef values = needRef();
|
||||
RegRef refs = needRef();
|
||||
|
||||
masm.unboxObject(Address(exn, WasmRuntimeExceptionObject::offsetOfValues()),
|
||||
values);
|
||||
masm.unboxObject(Address(exn, WasmRuntimeExceptionObject::offsetOfRefs()),
|
||||
refs);
|
||||
masm.unboxObject(Address(exn, WasmExceptionObject::offsetOfValues()), values);
|
||||
masm.unboxObject(Address(exn, WasmExceptionObject::offsetOfRefs()), refs);
|
||||
|
||||
# ifdef DEBUG
|
||||
Label ok;
|
||||
|
@ -10964,7 +10962,7 @@ bool BaseCompiler::emitThrow() {
|
|||
const uint32_t dataOffset =
|
||||
NativeObject::getFixedSlotOffset(ArrayBufferObject::DATA_SLOT);
|
||||
|
||||
Address exnValuesAddress(exn, WasmRuntimeExceptionObject::offsetOfValues());
|
||||
Address exnValuesAddress(exn, WasmExceptionObject::offsetOfValues());
|
||||
masm.unboxObject(exnValuesAddress, scratch);
|
||||
masm.loadPtr(Address(scratch, dataOffset), scratch);
|
||||
|
||||
|
|
|
@ -505,8 +505,7 @@ bool wasm::HandleThrow(JSContext* cx, WasmFrameIter& iter,
|
|||
|
||||
if (tryNote) {
|
||||
cx->clearPendingException();
|
||||
if (!exn.isObject() ||
|
||||
!exn.toObject().is<WasmRuntimeExceptionObject>()) {
|
||||
if (!exn.isObject() || !exn.toObject().is<WasmExceptionObject>()) {
|
||||
RootedObject obj(cx, WasmJSExceptionObject::create(cx, &exn));
|
||||
if (!obj) {
|
||||
MOZ_ASSERT(cx->isThrowingOutOfMemory());
|
||||
|
|
|
@ -1003,8 +1003,7 @@ bool Instance::initElems(uint32_t tableIndex, const ElemSegment& seg,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return AnyRef::fromJSObject(
|
||||
WasmRuntimeExceptionObject::create(cx, tag, buf, refs))
|
||||
return AnyRef::fromJSObject(WasmExceptionObject::create(cx, tag, buf, refs))
|
||||
.forCompiledCode();
|
||||
}
|
||||
|
||||
|
@ -1032,8 +1031,8 @@ bool Instance::initElems(uint32_t tableIndex, const ElemSegment& seg,
|
|||
MOZ_ASSERT(SASigGetLocalExceptionIndex.failureMode ==
|
||||
FailureMode::Infallible);
|
||||
|
||||
if (exn->is<WasmRuntimeExceptionObject>()) {
|
||||
ExceptionTag& exnTag = exn->as<WasmRuntimeExceptionObject>().tag();
|
||||
if (exn->is<WasmExceptionObject>()) {
|
||||
ExceptionTag& exnTag = exn->as<WasmExceptionObject>().tag();
|
||||
for (size_t i = 0; i < instance->exceptionTags().length(); i++) {
|
||||
ExceptionTag& tag = *instance->exceptionTags()[i];
|
||||
if (&tag == &exnTag) {
|
||||
|
@ -1053,9 +1052,8 @@ bool Instance::initElems(uint32_t tableIndex, const ElemSegment& seg,
|
|||
|
||||
JSContext* cx = TlsContext.get();
|
||||
|
||||
MOZ_ASSERT(exn->is<WasmRuntimeExceptionObject>());
|
||||
RootedWasmRuntimeExceptionObject exnObj(
|
||||
cx, &exn->as<WasmRuntimeExceptionObject>());
|
||||
MOZ_ASSERT(exn->is<WasmExceptionObject>());
|
||||
RootedWasmExceptionObject exnObj(cx, &exn->as<WasmExceptionObject>());
|
||||
|
||||
// TODO/AnyRef-boxing: With boxed immediates and strings, this may need to
|
||||
// handle other kinds of values.
|
||||
|
|
|
@ -555,23 +555,22 @@ bool js::wasm::GetImports(JSContext* cx, const Module& module,
|
|||
#ifdef ENABLE_WASM_EXCEPTIONS
|
||||
case DefinitionKind::Event: {
|
||||
const uint32_t index = eventIndex++;
|
||||
if (!v.isObject() || !v.toObject().is<WasmExceptionObject>()) {
|
||||
return ThrowBadImportType(cx, import.field.get(), "Exception");
|
||||
if (!v.isObject() || !v.toObject().is<WasmTagObject>()) {
|
||||
return ThrowBadImportType(cx, import.field.get(), "Tag");
|
||||
}
|
||||
|
||||
RootedWasmExceptionObject obj(cx,
|
||||
&v.toObject().as<WasmExceptionObject>());
|
||||
RootedWasmTagObject obj(cx, &v.toObject().as<WasmTagObject>());
|
||||
|
||||
// Checks whether the signature of the imported exception object matches
|
||||
// the signature declared in the exception import's EventDesc.
|
||||
if (obj->resultType() != events[index].resultType()) {
|
||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_WASM_BAD_EXN_SIG, import.module.get(),
|
||||
JSMSG_WASM_BAD_TAG_SIG, import.module.get(),
|
||||
import.field.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!imports->exceptionObjs.append(obj)) {
|
||||
if (!imports->tagObjs.append(obj)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
@ -3539,6 +3538,126 @@ bool WasmGlobalObject::type(JSContext* cx, unsigned argc, Value* vp) {
|
|||
}
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// WebAssembly.Tag class and methods
|
||||
|
||||
const JSClassOps WasmTagObject::classOps_ = {
|
||||
nullptr, // addProperty
|
||||
nullptr, // delProperty
|
||||
nullptr, // enumerate
|
||||
nullptr, // newEnumerate
|
||||
nullptr, // resolve
|
||||
nullptr, // mayResolve
|
||||
WasmTagObject::finalize, // finalize
|
||||
nullptr, // call
|
||||
nullptr, // hasInstance
|
||||
nullptr, // construct
|
||||
nullptr, // trace
|
||||
};
|
||||
|
||||
const JSClass WasmTagObject::class_ = {
|
||||
"WebAssembly.Tag",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(WasmTagObject::RESERVED_SLOTS) |
|
||||
JSCLASS_FOREGROUND_FINALIZE,
|
||||
&WasmTagObject::classOps_, &WasmTagObject::classSpec_};
|
||||
|
||||
const JSClass& WasmTagObject::protoClass_ = PlainObject::class_;
|
||||
|
||||
static constexpr char WasmTagName[] = "Tag";
|
||||
|
||||
const ClassSpec WasmTagObject::classSpec_ = {
|
||||
CreateWasmConstructor<WasmTagObject, WasmTagName>,
|
||||
GenericCreatePrototype<WasmTagObject>,
|
||||
WasmTagObject::static_methods,
|
||||
nullptr,
|
||||
WasmTagObject::methods,
|
||||
WasmTagObject::properties,
|
||||
nullptr,
|
||||
ClassSpec::DontDefineConstructor};
|
||||
|
||||
/* static */
|
||||
void WasmTagObject::finalize(JSFreeOp* fop, JSObject* obj) {
|
||||
WasmTagObject& exnObj = obj->as<WasmTagObject>();
|
||||
if (!exnObj.isNewborn()) {
|
||||
fop->release(obj, &exnObj.tag(), MemoryUse::WasmTagTag);
|
||||
fop->delete_(obj, &exnObj.valueTypes(), MemoryUse::WasmTagType);
|
||||
}
|
||||
}
|
||||
|
||||
bool WasmTagObject::construct(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (!ThrowIfNotConstructing(cx, args, "Tag")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: The JS API is not finalized and may specify a different behavior
|
||||
// here.
|
||||
// For now, we implement the same behavior as V8 and error when called.
|
||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_WASM_EXN_CONSTRUCTOR, "WebAssembly.Tag");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */
|
||||
WasmTagObject* WasmTagObject::create(JSContext* cx, const ValTypeVector& type,
|
||||
HandleObject proto) {
|
||||
AutoSetNewObjectMetadata metadata(cx);
|
||||
RootedWasmTagObject obj(cx,
|
||||
NewObjectWithGivenProto<WasmTagObject>(cx, proto));
|
||||
if (!obj) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(obj->isNewborn());
|
||||
|
||||
SharedExceptionTag tag = SharedExceptionTag(cx->new_<ExceptionTag>());
|
||||
if (!tag) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InitReservedSlot(obj, TAG_SLOT, tag.forget().take(), MemoryUse::WasmTagTag);
|
||||
|
||||
wasm::ValTypeVector* newValueTypes = js_new<ValTypeVector>();
|
||||
for (auto t : type) {
|
||||
if (!newValueTypes->append(t)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
InitReservedSlot(obj, TYPE_SLOT, newValueTypes, MemoryUse::WasmTagType);
|
||||
|
||||
MOZ_ASSERT(!obj->isNewborn());
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool WasmTagObject::isNewborn() const {
|
||||
MOZ_ASSERT(is<WasmTagObject>());
|
||||
return getReservedSlot(TYPE_SLOT).isUndefined();
|
||||
}
|
||||
|
||||
const JSPropertySpec WasmTagObject::properties[] = {
|
||||
JS_STRING_SYM_PS(toStringTag, "WebAssembly.Tag", JSPROP_READONLY),
|
||||
JS_PS_END};
|
||||
|
||||
const JSFunctionSpec WasmTagObject::methods[] = {JS_FS_END};
|
||||
|
||||
const JSFunctionSpec WasmTagObject::static_methods[] = {JS_FS_END};
|
||||
|
||||
wasm::ValTypeVector& WasmTagObject::valueTypes() const {
|
||||
return *(ValTypeVector*)getFixedSlot(TYPE_SLOT).toPrivate();
|
||||
};
|
||||
|
||||
wasm::ResultType WasmTagObject::resultType() const {
|
||||
return wasm::ResultType::Vector(valueTypes());
|
||||
}
|
||||
|
||||
ExceptionTag& WasmTagObject::tag() const {
|
||||
return *(ExceptionTag*)getReservedSlot(TAG_SLOT).toPrivate();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// WebAssembly.Exception class and methods
|
||||
|
||||
|
@ -3581,7 +3700,6 @@ void WasmExceptionObject::finalize(JSFreeOp* fop, JSObject* obj) {
|
|||
WasmExceptionObject& exnObj = obj->as<WasmExceptionObject>();
|
||||
if (!exnObj.isNewborn()) {
|
||||
fop->release(obj, &exnObj.tag(), MemoryUse::WasmExceptionTag);
|
||||
fop->delete_(obj, &exnObj.valueTypes(), MemoryUse::WasmExceptionType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3592,9 +3710,8 @@ bool WasmExceptionObject::construct(JSContext* cx, unsigned argc, Value* vp) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// FIXME: The JS API is not finalized and may specify a different behavior
|
||||
// here.
|
||||
// For now, we implement the same behavior as V8 and error when called.
|
||||
// FIXME: When the JS API is finalized, it may be possible to construct
|
||||
// WebAssembly.Exception instances from JS, but not for now.
|
||||
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_WASM_EXN_CONSTRUCTOR, "WebAssembly.Exception");
|
||||
|
||||
|
@ -3603,8 +3720,12 @@ bool WasmExceptionObject::construct(JSContext* cx, unsigned argc, Value* vp) {
|
|||
|
||||
/* static */
|
||||
WasmExceptionObject* WasmExceptionObject::create(JSContext* cx,
|
||||
const ValTypeVector& type,
|
||||
HandleObject proto) {
|
||||
wasm::SharedExceptionTag tag,
|
||||
HandleArrayBufferObject values,
|
||||
HandleArrayObject refs) {
|
||||
RootedObject proto(
|
||||
cx, &cx->global()->getPrototype(JSProto_WasmException).toObject());
|
||||
|
||||
AutoSetNewObjectMetadata metadata(cx);
|
||||
RootedWasmExceptionObject obj(
|
||||
cx, NewObjectWithGivenProto<WasmExceptionObject>(cx, proto));
|
||||
|
@ -3613,23 +3734,11 @@ WasmExceptionObject* WasmExceptionObject::create(JSContext* cx,
|
|||
}
|
||||
|
||||
MOZ_ASSERT(obj->isNewborn());
|
||||
|
||||
SharedExceptionTag tag = SharedExceptionTag(cx->new_<ExceptionTag>());
|
||||
if (!tag) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InitReservedSlot(obj, TAG_SLOT, tag.forget().take(),
|
||||
MemoryUse::WasmExceptionTag);
|
||||
|
||||
wasm::ValTypeVector* newValueTypes = js_new<ValTypeVector>();
|
||||
for (auto t : type) {
|
||||
if (!newValueTypes->append(t)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
InitReservedSlot(obj, TYPE_SLOT, newValueTypes, MemoryUse::WasmExceptionType);
|
||||
obj->initFixedSlot(VALUES_SLOT, ObjectValue(*values));
|
||||
obj->initFixedSlot(REFS_SLOT, ObjectValue(*refs));
|
||||
|
||||
MOZ_ASSERT(!obj->isNewborn());
|
||||
|
||||
|
@ -3638,7 +3747,7 @@ WasmExceptionObject* WasmExceptionObject::create(JSContext* cx,
|
|||
|
||||
bool WasmExceptionObject::isNewborn() const {
|
||||
MOZ_ASSERT(is<WasmExceptionObject>());
|
||||
return getReservedSlot(TYPE_SLOT).isUndefined();
|
||||
return getReservedSlot(REFS_SLOT).isUndefined();
|
||||
}
|
||||
|
||||
const JSPropertySpec WasmExceptionObject::properties[] = {
|
||||
|
@ -3649,126 +3758,11 @@ const JSFunctionSpec WasmExceptionObject::methods[] = {JS_FS_END};
|
|||
|
||||
const JSFunctionSpec WasmExceptionObject::static_methods[] = {JS_FS_END};
|
||||
|
||||
wasm::ValTypeVector& WasmExceptionObject::valueTypes() const {
|
||||
return *(ValTypeVector*)getFixedSlot(TYPE_SLOT).toPrivate();
|
||||
};
|
||||
|
||||
wasm::ResultType WasmExceptionObject::resultType() const {
|
||||
return wasm::ResultType::Vector(valueTypes());
|
||||
}
|
||||
|
||||
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_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,
|
||||
HandleArrayObject refs) {
|
||||
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));
|
||||
obj->initFixedSlot(REFS_SLOT, ObjectValue(*refs));
|
||||
|
||||
MOZ_ASSERT(!obj->isNewborn());
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool WasmRuntimeExceptionObject::isNewborn() const {
|
||||
MOZ_ASSERT(is<WasmRuntimeExceptionObject>());
|
||||
return getReservedSlot(REFS_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();
|
||||
}
|
||||
|
||||
ArrayObject& WasmRuntimeExceptionObject::refs() const {
|
||||
ArrayObject& WasmExceptionObject::refs() const {
|
||||
return getReservedSlot(REFS_SLOT).toObject().as<ArrayObject>();
|
||||
}
|
||||
|
||||
|
@ -4749,8 +4743,8 @@ static bool WebAssemblyClassFinish(JSContext* cx, HandleObject object,
|
|||
{"Table", JSProto_WasmTable},
|
||||
{"Global", JSProto_WasmGlobal},
|
||||
#ifdef ENABLE_WASM_EXCEPTIONS
|
||||
{"Tag", JSProto_WasmTag},
|
||||
{"Exception", JSProto_WasmException},
|
||||
{"RuntimeException", JSProto_WasmRuntimeException},
|
||||
#endif
|
||||
{"CompileError", GetExceptionProtoKey(JSEXN_WASMCOMPILEERROR)},
|
||||
{"LinkError", GetExceptionProtoKey(JSEXN_WASMLINKERROR)},
|
||||
|
|
|
@ -488,10 +488,10 @@ class WasmTableObject : public NativeObject {
|
|||
#endif
|
||||
};
|
||||
|
||||
// The class of WebAssembly.Exception. This class is used to track exception
|
||||
// The class of WebAssembly.Tag. This class is used to track exception tag
|
||||
// types for exports and imports.
|
||||
|
||||
class WasmExceptionObject : public NativeObject {
|
||||
class WasmTagObject : public NativeObject {
|
||||
static const unsigned TAG_SLOT = 0;
|
||||
static const unsigned TYPE_SLOT = 1;
|
||||
|
||||
|
@ -509,9 +509,8 @@ class WasmExceptionObject : public NativeObject {
|
|||
static const JSFunctionSpec static_methods[];
|
||||
static bool construct(JSContext*, unsigned, Value*);
|
||||
|
||||
static WasmExceptionObject* create(JSContext* cx,
|
||||
const wasm::ValTypeVector& type,
|
||||
HandleObject proto);
|
||||
static WasmTagObject* create(JSContext* cx, const wasm::ValTypeVector& type,
|
||||
HandleObject proto);
|
||||
bool isNewborn() const;
|
||||
|
||||
wasm::ValTypeVector& valueTypes() const;
|
||||
|
@ -519,11 +518,11 @@ class WasmExceptionObject : public NativeObject {
|
|||
wasm::ExceptionTag& tag() const;
|
||||
};
|
||||
|
||||
// The class of WebAssembly.RuntimeException. This class is used for
|
||||
// The class of WebAssembly.Exception. 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 {
|
||||
class WasmExceptionObject : public NativeObject {
|
||||
static const unsigned TAG_SLOT = 0;
|
||||
static const unsigned VALUES_SLOT = 1;
|
||||
static const unsigned REFS_SLOT = 2;
|
||||
|
@ -542,10 +541,10 @@ class WasmRuntimeExceptionObject : public NativeObject {
|
|||
static const JSFunctionSpec static_methods[];
|
||||
static bool construct(JSContext*, unsigned, Value*);
|
||||
|
||||
static WasmRuntimeExceptionObject* create(JSContext* cx,
|
||||
wasm::SharedExceptionTag tag,
|
||||
Handle<ArrayBufferObject*> values,
|
||||
HandleArrayObject refs);
|
||||
static WasmExceptionObject* create(JSContext* cx,
|
||||
wasm::SharedExceptionTag tag,
|
||||
Handle<ArrayBufferObject*> values,
|
||||
HandleArrayObject refs);
|
||||
bool isNewborn() const;
|
||||
|
||||
wasm::ExceptionTag& tag() const;
|
||||
|
|
|
@ -755,15 +755,16 @@ bool Module::instantiateMemory(JSContext* cx,
|
|||
}
|
||||
|
||||
#ifdef ENABLE_WASM_EXCEPTIONS
|
||||
bool Module::instantiateImportedException(
|
||||
JSContext* cx, Handle<WasmExceptionObject*> exnObj,
|
||||
WasmExceptionObjectVector& exnObjs, SharedExceptionTagVector* tags) const {
|
||||
MOZ_ASSERT(exnObj);
|
||||
// The check whether the EventDesc signature matches the exnObj value types
|
||||
bool Module::instantiateImportedTag(JSContext* cx,
|
||||
Handle<WasmTagObject*> tagObj,
|
||||
WasmTagObjectVector& tagObjs,
|
||||
SharedExceptionTagVector* tags) const {
|
||||
MOZ_ASSERT(tagObj);
|
||||
// The check whether the EventDesc signature matches the tagObj value types
|
||||
// is done by js::wasm::GetImports().
|
||||
|
||||
// Collects the exception tag from the imported exception.
|
||||
ExceptionTag& tag = exnObj->tag();
|
||||
// Collects the exception tag from the imported tag.
|
||||
ExceptionTag& tag = tagObj->tag();
|
||||
|
||||
if (!tags->append(&tag)) {
|
||||
ReportOutOfMemory(cx);
|
||||
|
@ -773,40 +774,39 @@ bool Module::instantiateImportedException(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Module::instantiateLocalException(JSContext* cx, const EventDesc& ed,
|
||||
WasmExceptionObjectVector& exnObjs,
|
||||
SharedExceptionTagVector* tags,
|
||||
uint32_t exnIndex) const {
|
||||
bool Module::instantiateLocalTag(JSContext* cx, const EventDesc& ed,
|
||||
WasmTagObjectVector& tagObjs,
|
||||
SharedExceptionTagVector* tags,
|
||||
uint32_t tagIndex) const {
|
||||
SharedExceptionTag tag;
|
||||
// Extend exnObjs in anticipation of an exported exception object.
|
||||
if (exnObjs.length() <= exnIndex && !exnObjs.resize(exnIndex + 1)) {
|
||||
// Extend tagObjs in anticipation of an exported tag object.
|
||||
if (tagObjs.length() <= tagIndex && !tagObjs.resize(tagIndex + 1)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ed.isExport) {
|
||||
// If the exception description is exported, create an export exception
|
||||
// If the tag description is exported, create an export tag
|
||||
// object for it.
|
||||
RootedObject proto(
|
||||
cx, &cx->global()->getPrototype(JSProto_WasmException).toObject());
|
||||
RootedWasmExceptionObject exnObj(
|
||||
cx, WasmExceptionObject::create(cx, ed.type, proto));
|
||||
if (!exnObj) {
|
||||
RootedObject proto(cx,
|
||||
&cx->global()->getPrototype(JSProto_WasmTag).toObject());
|
||||
RootedWasmTagObject tagObj(cx, WasmTagObject::create(cx, ed.type, proto));
|
||||
if (!tagObj) {
|
||||
return false;
|
||||
}
|
||||
// Take the exception tag that was created inside the WasmExceptionObject.
|
||||
tag = &exnObj->tag();
|
||||
// Save the new export exception object.
|
||||
exnObjs[exnIndex] = exnObj;
|
||||
// Take the exception tag that was created inside the WasmTagObject.
|
||||
tag = &tagObj->tag();
|
||||
// Save the new export tag object.
|
||||
tagObjs[tagIndex] = tagObj;
|
||||
} else {
|
||||
// Create a new tag for every non exported exception.
|
||||
// Create a new exception tag for every non exported tag.
|
||||
tag = SharedExceptionTag(cx->new_<ExceptionTag>());
|
||||
if (!tag) {
|
||||
return false;
|
||||
}
|
||||
// The exnObj is null if the exception is neither exported nor imported.
|
||||
// The tagObj is null if the tag is neither exported nor imported.
|
||||
}
|
||||
// Collect a tag for every exception.
|
||||
// Collect an exception tag for every tag.
|
||||
if (!tags->emplaceBack(tag)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
|
@ -815,22 +815,21 @@ bool Module::instantiateLocalException(JSContext* cx, const EventDesc& ed,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Module::instantiateExceptions(JSContext* cx,
|
||||
WasmExceptionObjectVector& exnObjs,
|
||||
SharedExceptionTagVector* tags) const {
|
||||
uint32_t exnIndex = 0;
|
||||
bool Module::instantiateTags(JSContext* cx, WasmTagObjectVector& tagObjs,
|
||||
SharedExceptionTagVector* tags) const {
|
||||
uint32_t tagIndex = 0;
|
||||
for (const EventDesc& ed : metadata().events) {
|
||||
if (exnIndex < exnObjs.length()) {
|
||||
Rooted<WasmExceptionObject*> exnObj(cx, exnObjs[exnIndex]);
|
||||
if (!instantiateImportedException(cx, exnObj, exnObjs, tags)) {
|
||||
if (tagIndex < tagObjs.length()) {
|
||||
Rooted<WasmTagObject*> tagObj(cx, tagObjs[tagIndex]);
|
||||
if (!instantiateImportedTag(cx, tagObj, tagObjs, tags)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!instantiateLocalException(cx, ed, exnObjs, tags, exnIndex)) {
|
||||
if (!instantiateLocalTag(cx, ed, tagObjs, tags, tagIndex)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
exnIndex++;
|
||||
tagIndex++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1111,15 +1110,12 @@ static bool GetGlobalExport(JSContext* cx, HandleWasmInstanceObject instanceObj,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool CreateExportObject(JSContext* cx,
|
||||
HandleWasmInstanceObject instanceObj,
|
||||
const JSFunctionVector& funcImports,
|
||||
const WasmTableObjectVector& tableObjs,
|
||||
HandleWasmMemoryObject memoryObj,
|
||||
const WasmExceptionObjectVector& exceptionObjs,
|
||||
const ValVector& globalImportValues,
|
||||
const WasmGlobalObjectVector& globalObjs,
|
||||
const ExportVector& exports) {
|
||||
static bool CreateExportObject(
|
||||
JSContext* cx, HandleWasmInstanceObject instanceObj,
|
||||
const JSFunctionVector& funcImports, const WasmTableObjectVector& tableObjs,
|
||||
HandleWasmMemoryObject memoryObj, const WasmTagObjectVector& tagObjs,
|
||||
const ValVector& globalImportValues,
|
||||
const WasmGlobalObjectVector& globalObjs, const ExportVector& exports) {
|
||||
const Instance& instance = instanceObj->instance();
|
||||
const Metadata& metadata = instance.metadata();
|
||||
const GlobalDescVector& globals = metadata.globals;
|
||||
|
@ -1186,7 +1182,7 @@ static bool CreateExportObject(JSContext* cx,
|
|||
}
|
||||
#ifdef ENABLE_WASM_EXCEPTIONS
|
||||
case DefinitionKind::Event: {
|
||||
val = ObjectValue(*exceptionObjs[exp.eventIndex()]);
|
||||
val = ObjectValue(*tagObjs[exp.eventIndex()]);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -1230,7 +1226,7 @@ bool Module::instantiate(JSContext* cx, ImportValues& imports,
|
|||
|
||||
SharedExceptionTagVector tags;
|
||||
#ifdef ENABLE_WASM_EXCEPTIONS
|
||||
if (!instantiateExceptions(cx, imports.exceptionObjs, &tags)) {
|
||||
if (!instantiateTags(cx, imports.tagObjs, &tags)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
@ -1281,7 +1277,7 @@ bool Module::instantiate(JSContext* cx, ImportValues& imports,
|
|||
}
|
||||
|
||||
if (!CreateExportObject(cx, instance, imports.funcs, tableObjs.get(), memory,
|
||||
imports.exceptionObjs, imports.globalValues,
|
||||
imports.tagObjs, imports.globalValues,
|
||||
imports.globalObjs, exports_)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ struct ImportValues {
|
|||
JSFunctionVector funcs;
|
||||
WasmTableObjectVector tables;
|
||||
WasmMemoryObject* memory;
|
||||
WasmExceptionObjectVector exceptionObjs;
|
||||
WasmTagObjectVector tagObjs;
|
||||
WasmGlobalObjectVector globalObjs;
|
||||
ValVector globalValues;
|
||||
|
||||
|
@ -57,7 +57,7 @@ struct ImportValues {
|
|||
if (memory) {
|
||||
TraceRoot(trc, &memory, "import values memory");
|
||||
}
|
||||
exceptionObjs.trace(trc);
|
||||
tagObjs.trace(trc);
|
||||
globalObjs.trace(trc);
|
||||
globalValues.trace(trc);
|
||||
}
|
||||
|
@ -124,16 +124,15 @@ class Module : public JS::WasmModule {
|
|||
bool instantiateMemory(JSContext* cx,
|
||||
MutableHandleWasmMemoryObject memory) const;
|
||||
#ifdef ENABLE_WASM_EXCEPTIONS
|
||||
bool instantiateImportedException(JSContext* cx,
|
||||
Handle<WasmExceptionObject*> exnObj,
|
||||
WasmExceptionObjectVector& exnObjs,
|
||||
SharedExceptionTagVector* tags) const;
|
||||
bool instantiateLocalException(JSContext* cx, const EventDesc& ed,
|
||||
WasmExceptionObjectVector& exnObjs,
|
||||
SharedExceptionTagVector* tags,
|
||||
uint32_t exnIndex) const;
|
||||
bool instantiateExceptions(JSContext* cx, WasmExceptionObjectVector& exnObjs,
|
||||
SharedExceptionTagVector* tags) const;
|
||||
bool instantiateImportedTag(JSContext* cx, Handle<WasmTagObject*> tagObj,
|
||||
WasmTagObjectVector& tagObjs,
|
||||
SharedExceptionTagVector* tags) const;
|
||||
bool instantiateLocalTag(JSContext* cx, const EventDesc& ed,
|
||||
WasmTagObjectVector& tagObjs,
|
||||
SharedExceptionTagVector* tags,
|
||||
uint32_t tagIndex) const;
|
||||
bool instantiateTags(JSContext* cx, WasmTagObjectVector& tagObjs,
|
||||
SharedExceptionTagVector* tags) const;
|
||||
#endif
|
||||
bool instantiateImportedTable(JSContext* cx, const TableDesc& td,
|
||||
Handle<WasmTableObject*> table,
|
||||
|
|
|
@ -60,13 +60,12 @@ using WasmGlobalObjectVector =
|
|||
GCVector<WasmGlobalObject*, 0, SystemAllocPolicy>;
|
||||
using RootedWasmGlobalObject = Rooted<WasmGlobalObject*>;
|
||||
|
||||
class WasmExceptionObject;
|
||||
using WasmExceptionObjectVector =
|
||||
GCVector<WasmExceptionObject*, 0, SystemAllocPolicy>;
|
||||
using RootedWasmExceptionObject = Rooted<WasmExceptionObject*>;
|
||||
class WasmTagObject;
|
||||
using WasmTagObjectVector = GCVector<WasmTagObject*, 0, SystemAllocPolicy>;
|
||||
using RootedWasmTagObject = Rooted<WasmTagObject*>;
|
||||
|
||||
class WasmRuntimeExceptionObject;
|
||||
using RootedWasmRuntimeExceptionObject = Rooted<WasmRuntimeExceptionObject*>;
|
||||
class WasmExceptionObject;
|
||||
using RootedWasmExceptionObject = Rooted<WasmExceptionObject*>;
|
||||
|
||||
namespace wasm {
|
||||
|
||||
|
|
|
@ -81,12 +81,16 @@ class Instance;
|
|||
class Table;
|
||||
|
||||
// Exception tags are used to uniquely identify exceptions. They are stored
|
||||
// in a vector in Instances and used by both WebAssembly.Exception for import
|
||||
// and export, and by the representation of thrown exceptions.
|
||||
// in a vector in Instances and used by both WebAssembly.Tag for import
|
||||
// and export, and by WebAssembly.Exception for thrown exceptions.
|
||||
//
|
||||
// Since an exception tag is a (trivial) substructure of AtomicRefCounted, the
|
||||
// RefPtr SharedExceptionTag can have many instances/modules referencing a
|
||||
// single constant exception tag.
|
||||
// RefPtr SharedTag can have many instances/modules referencing a single
|
||||
// constant exception tag.
|
||||
//
|
||||
// It is possible that other proposals will start using tags as well, in which
|
||||
// case it may be worth generalizing this representation for other kinds of
|
||||
// tags.
|
||||
|
||||
struct ExceptionTag : AtomicRefCounted<ExceptionTag> {
|
||||
ExceptionTag() = default;
|
||||
|
@ -97,7 +101,7 @@ using SharedExceptionTagVector =
|
|||
|
||||
// WasmJSExceptionObject wraps a JS Value in order to provide a uniform
|
||||
// method of handling JS thrown exceptions. Exceptions originating in Wasm
|
||||
// are WebAssemby.RuntimeException objects, whereas exceptions from JS are
|
||||
// are WebAssemby.Exception objects, whereas exceptions from JS are
|
||||
// wrapped as WasmJSExceptionObject objects.
|
||||
class WasmJSExceptionObject : public NativeObject {
|
||||
static const unsigned VALUE_SLOT = 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче