Bug 1669784 - Merge TypedObject namespace into WebAssembly namespace, gated on GC feature. r=lth

This commit merges the TypedObject namespace into the WebAssembly namespace, and
only exposes the TypedObject definitions when the GC feature is enabled.

A future commit will remove the TypedObject definitions from the namespace, but we
still need the infrastructure from this commit for storing the TypedObject definitions
in private slots in the namespace.

Differential Revision: https://phabricator.services.mozilla.com/D92857
This commit is contained in:
Ryan Hunt 2020-10-12 21:01:39 +00:00
parent 3cf9a86691
commit 67e0a28855
14 changed files with 122 additions and 200 deletions

View File

@ -67,7 +67,6 @@ var ecmaGlobals = [
"String",
"Symbol",
"SyntaxError",
{ name: "TypedObject", nightly: true },
"TypeError",
"Uint16Array",
"Uint32Array",

View File

@ -96,7 +96,6 @@ var ecmaGlobals = [
{ name: "String", insecureContext: true },
{ name: "Symbol", insecureContext: true },
{ name: "SyntaxError", insecureContext: true },
{ name: "TypedObject", insecureContext: true, nightly: true },
{ name: "TypeError", insecureContext: true },
{ name: "Uint16Array", insecureContext: true },
{ name: "Uint32Array", insecureContext: true },

View File

@ -76,7 +76,6 @@ var ecmaGlobals = [
{ name: "String", insecureContext: true },
{ name: "Symbol", insecureContext: true },
{ name: "SyntaxError", insecureContext: true },
{ name: "TypedObject", insecureContext: true, nightly: true },
{ name: "TypeError", insecureContext: true },
{ name: "Uint16Array", insecureContext: true },
{ name: "Uint32Array", insecureContext: true },

View File

@ -494,22 +494,6 @@ option('--enable-wasm-codegen-debug',
set_config('WASM_CODEGEN_DEBUG', depends_if('--enable-wasm-codegen-debug')(lambda x: True))
set_define('WASM_CODEGEN_DEBUG', depends_if('--enable-wasm-codegen-debug')(lambda x: True))
# Support for typed objects.
# =====================================================
@depends(milestone.is_nightly)
def default_typed_objects(is_nightly):
return is_nightly
option('--enable-typed-objects',
default=default_typed_objects,
help='{Enable|Disable} typed objects')
set_config('JS_HAS_TYPED_OBJECTS', depends_if('--enable-typed-objects')(lambda x: True))
set_define('JS_HAS_TYPED_OBJECTS', depends_if('--enable-typed-objects')(lambda x: True))
# Support for WebAssembly reference types.
# =====================================================
@ -552,24 +536,24 @@ set_define('ENABLE_WASM_FUNCTION_REFERENCES', wasm_function_references)
# Support for WebAssembly GC.
# ===========================
@depends(milestone.is_nightly, '--enable-wasm-function-references', '--enable-typed-objects')
def default_wasm_gc(is_nightly, function_references, typed_objects):
if is_nightly and function_references and typed_objects:
@depends(milestone.is_nightly, '--enable-wasm-function-references')
def default_wasm_gc(is_nightly, function_references):
if is_nightly and function_references:
return True
option('--enable-wasm-gc',
default=default_wasm_gc,
help='{Enable|Disable} WebAssembly GC')
@depends('--enable-wasm-gc', '--enable-wasm-function-references', '--enable-typed-objects')
def wasm_gc(value, function_references, typed_objects):
@depends('--enable-wasm-gc', '--enable-wasm-function-references')
def wasm_gc(value, function_references):
if not value:
return
if function_references and typed_objects:
if function_references:
return True
die('--enable-wasm-gc only possible with --enable-wasm-function-references and --enable-typed-objects')
die('--enable-wasm-gc only possible with --enable-wasm-function-references')
set_config('ENABLE_WASM_GC', wasm_gc)
set_define('ENABLE_WASM_GC', wasm_gc)

View File

@ -40,13 +40,7 @@
# define IF_INTL(REAL, IMAGINARY) IMAGINARY
#endif
#ifdef JS_HAS_TYPED_OBJECTS
# define IF_TYPEDOBJ(REAL, IMAGINARY) REAL
#else
# define IF_TYPEDOBJ(REAL, IMAGINARY) IMAGINARY
#endif
#define JS_FOR_PROTOTYPES_(REAL, IMAGINARY, REAL_IF_INTL, REAL_IF_BDATA) \
#define JS_FOR_PROTOTYPES_(REAL, IMAGINARY, REAL_IF_INTL) \
IMAGINARY(Null, dummy) \
REAL(Object, OCLASP(Plain)) \
REAL(Function, &JSFunction::class_) \
@ -100,7 +94,6 @@
REAL_IF_INTL(NumberFormat, OCLASP(NumberFormat)) \
REAL_IF_INTL(PluralRules, OCLASP(PluralRules)) \
REAL_IF_INTL(RelativeTimeFormat, OCLASP(RelativeTimeFormat)) \
REAL_IF_BDATA(TypedObject, OCLASP(TypedObjectModule)) \
REAL(Reflect, CLASP(Reflect)) \
REAL(WeakSet, OCLASP(WeakSet)) \
REAL(TypedArray, &js::TypedArrayObject::sharedTypedArrayPrototypeClass) \
@ -122,7 +115,7 @@
REAL(WritableStreamDefaultWriter, &js::WritableStreamDefaultWriter::class_) \
REAL(ByteLengthQueuingStrategy, &js::ByteLengthQueuingStrategy::class_) \
REAL(CountQueuingStrategy, &js::CountQueuingStrategy::class_) \
REAL(WebAssembly, CLASP(WebAssembly)) \
REAL(WebAssembly, OCLASP(WasmNamespace)) \
REAL(WasmModule, OCLASP(WasmModule)) \
REAL(WasmInstance, OCLASP(WasmInstance)) \
REAL(WasmMemory, OCLASP(WasmMemory)) \
@ -133,9 +126,8 @@
REAL(Iterator, OCLASP(Iterator)) \
REAL(AsyncIterator, OCLASP(AsyncIterator))
#define JS_FOR_PROTOTYPES(REAL, IMAGINARY) \
JS_FOR_PROTOTYPES_(REAL, IMAGINARY, IF_INTL(REAL, IMAGINARY), \
IF_TYPEDOBJ(REAL, IMAGINARY))
#define JS_FOR_PROTOTYPES(REAL, IMAGINARY) \
JS_FOR_PROTOTYPES_(REAL, IMAGINARY, IF_INTL(REAL, IMAGINARY))
#define JS_FOR_EACH_PROTOTYPE(MACRO) JS_FOR_PROTOTYPES(MACRO, MACRO)

View File

@ -452,15 +452,6 @@ static bool GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
#ifdef JS_HAS_TYPED_OBJECTS
value = BooleanValue(true);
#else
value = BooleanValue(false);
#endif
if (!JS_SetProperty(cx, info, "typed-objects", value)) {
return false;
}
#ifdef JS_HAS_INTL_API
value = BooleanValue(true);
#else

View File

@ -35,9 +35,6 @@
/* Define to 1 if SpiderMonkey should include trace logging support. */
#undef JS_TRACE_LOGGING
/* Define to 1 if SpiderMonkey should include typed objects support. */
#undef JS_HAS_TYPED_OBJECTS
/* Define to 1 if SpiderMonkey should include support for the Intl API. */
#undef JS_HAS_INTL_API

View File

@ -57,9 +57,6 @@
#include "vm/PIC.h"
#include "vm/RegExpStatics.h"
#include "vm/RegExpStaticsObject.h"
#ifdef JS_HAS_TYPED_OBJECTS
# include "wasm/TypedObject.h"
#endif
#include "gc/FreeOp-inl.h"
#include "vm/JSObject-inl.h"
@ -75,7 +72,6 @@ extern const JSClass IntlClass;
extern const JSClass JSONClass;
extern const JSClass MathClass;
extern const JSClass ReflectClass;
extern const JSClass WebAssemblyClass;
} // namespace js
@ -93,13 +89,13 @@ JS_FRIEND_API const JSClass* js::ProtoKeyToClass(JSProtoKey key) {
}
// This method is not in the header file to avoid having to include
// TypedObject.h from GlobalObject.h. It is not generally perf
// WasmJS.h from GlobalObject.h. It is not generally perf
// sensitive.
TypedObjectModuleObject& js::GlobalObject::getTypedObjectModule() const {
Value v = getConstructor(JSProto_TypedObject);
// only gets called from contexts where TypedObject must be initialized
WasmNamespaceObject& js::GlobalObject::getWebAssemblyNamespace() const {
Value v = getConstructor(JSProto_WebAssembly);
// only gets called from contexts where WebAssembly must be initialized
MOZ_ASSERT(v.isObject());
return v.toObject().as<TypedObjectModuleObject>();
return v.toObject().as<WasmNamespaceObject>();
}
/* static */
@ -181,11 +177,6 @@ bool GlobalObject::skipDeselectedConstructor(JSContext* cx, JSProtoKey key) {
return false;
#endif
#ifdef JS_HAS_TYPED_OBJECTS
case JSProto_TypedObject:
return false;
#endif
case JSProto_ReadableStream:
case JSProto_ReadableStreamDefaultReader:
case JSProto_ReadableStreamDefaultController:

View File

@ -55,7 +55,7 @@ class LexicalEnvironmentObject;
class PlainObject;
class RegExpStatics;
class TypeDescr;
class TypedObjectModuleObject;
class WasmNamespaceObject;
enum class ReferenceType;
@ -500,9 +500,9 @@ class GlobalObject : public NativeObject {
return &global->getPrototype(JSProto_WeakSet).toObject().as<NativeObject>();
}
static JSObject* getOrCreateTypedObjectModule(JSContext* cx,
Handle<GlobalObject*> global) {
return getOrCreateConstructor(cx, JSProto_TypedObject);
static JSObject* getOrCreateWebAssemblyNamespace(
JSContext* cx, Handle<GlobalObject*> global) {
return getOrCreateConstructor(cx, JSProto_WebAssembly);
}
static TypeDescr* getOrCreateScalarTypeDescr(JSContext* cx,
@ -513,7 +513,7 @@ class GlobalObject : public NativeObject {
Handle<GlobalObject*> global,
ReferenceType type);
TypedObjectModuleObject& getTypedObjectModule() const;
WasmNamespaceObject& getWebAssemblyNamespace() const;
static bool ensureModulePrototypesCreated(JSContext* cx,
Handle<GlobalObject*> global);
@ -873,10 +873,6 @@ class GlobalObject : public NativeObject {
static bool initRequestedModuleProto(JSContext* cx,
Handle<GlobalObject*> global);
// Implemented in wasm/TypedObject.cpp
static bool initTypedObjectModule(JSContext* cx,
Handle<GlobalObject*> global);
static bool initStandardClasses(JSContext* cx, Handle<GlobalObject*> global);
static bool initSelfHostingBuiltins(JSContext* cx,
Handle<GlobalObject*> global,

View File

@ -27,6 +27,7 @@
#include "vm/TypedArrayObject.h"
#include "vm/Uint8Clamped.h"
#include "wasm/WasmJS.h" // WasmNamespaceObject
#include "wasm/WasmTypes.h" // WasmValueBox
#include "gc/Marking-inl.h"
#include "gc/Nursery-inl.h"
@ -44,12 +45,6 @@ using mozilla::PointerRangeSize;
using namespace js;
const JSClass js::TypedObjectModuleObject::class_ = {
"TypedObject",
JSCLASS_HAS_RESERVED_SLOTS(SlotCount) |
JSCLASS_HAS_CACHED_PROTO(JSProto_TypedObject),
JS_NULL_CLASS_OPS, &classSpec_};
template <class T>
static inline T* ToObjectIf(HandleValue value) {
if (!value.isObject()) {
@ -236,28 +231,28 @@ TypeDescr* GlobalObject::getOrCreateScalarTypeDescr(
int32_t slot = 0;
switch (scalarType) {
case Scalar::Int32:
slot = TypedObjectModuleObject::Int32Desc;
slot = WasmNamespaceObject::Int32Desc;
break;
case Scalar::Int64:
slot = TypedObjectModuleObject::Int64Desc;
slot = WasmNamespaceObject::Int64Desc;
break;
case Scalar::Float32:
slot = TypedObjectModuleObject::Float32Desc;
slot = WasmNamespaceObject::Float32Desc;
break;
case Scalar::Float64:
slot = TypedObjectModuleObject::Float64Desc;
slot = WasmNamespaceObject::Float64Desc;
break;
default:
MOZ_CRASH("NYI");
}
Rooted<TypedObjectModuleObject*> module(
cx, &GlobalObject::getOrCreateTypedObjectModule(cx, global)
->as<TypedObjectModuleObject>());
if (!module) {
Rooted<WasmNamespaceObject*> namespaceObject(
cx, &GlobalObject::getOrCreateWebAssemblyNamespace(cx, global)
->as<WasmNamespaceObject>());
if (!namespaceObject) {
return nullptr;
}
return &module->getReservedSlot(slot).toObject().as<TypeDescr>();
return &namespaceObject->getReservedSlot(slot).toObject().as<TypeDescr>();
}
/* static */
@ -266,22 +261,22 @@ TypeDescr* GlobalObject::getOrCreateReferenceTypeDescr(
int32_t slot = 0;
switch (type) {
case ReferenceType::TYPE_OBJECT:
slot = TypedObjectModuleObject::ObjectDesc;
slot = WasmNamespaceObject::ObjectDesc;
break;
case ReferenceType::TYPE_WASM_ANYREF:
slot = TypedObjectModuleObject::WasmAnyRefDesc;
slot = WasmNamespaceObject::WasmAnyRefDesc;
break;
default:
MOZ_CRASH("NYI");
}
Rooted<TypedObjectModuleObject*> module(
cx, &GlobalObject::getOrCreateTypedObjectModule(cx, global)
->as<TypedObjectModuleObject>());
if (!module) {
Rooted<WasmNamespaceObject*> namespaceObject(
cx, &GlobalObject::getOrCreateWebAssemblyNamespace(cx, global)
->as<WasmNamespaceObject>());
if (!namespaceObject) {
return nullptr;
}
return &module->getReservedSlot(slot).toObject().as<TypeDescr>();
return &namespaceObject->getReservedSlot(slot).toObject().as<TypeDescr>();
}
/***************************************************************************
@ -849,7 +844,8 @@ TypeDescr& StructTypeDescr::fieldDescr(size_t index) const {
// Here `T` is either `ScalarTypeDescr` or `ReferenceTypeDescr`
template <typename T>
static bool DefineSimpleTypeDescr(JSContext* cx, Handle<GlobalObject*> global,
HandleObject module, typename T::Type type,
Handle<WasmNamespaceObject*> namespaceObject,
typename T::Type type,
HandlePropertyName className) {
RootedObject objProto(cx,
GlobalObject::getOrCreateObjectPrototype(cx, global));
@ -885,7 +881,7 @@ static bool DefineSimpleTypeDescr(JSContext* cx, Handle<GlobalObject*> global,
descr->initReservedSlot(TypeDescr::Proto, ObjectValue(*proto));
RootedValue descrValue(cx, ObjectValue(*descr));
if (!DefineDataProperty(cx, module, className, descrValue, 0)) {
if (!DefineDataProperty(cx, namespaceObject, className, descrValue, 0)) {
return false;
}
@ -903,10 +899,10 @@ static bool DefineSimpleTypeDescr(JSContext* cx, Handle<GlobalObject*> global,
///////////////////////////////////////////////////////////////////////////
template <typename T>
static JSObject* DefineMetaTypeDescr(JSContext* cx, const char* name,
Handle<GlobalObject*> global,
Handle<TypedObjectModuleObject*> module,
TypedObjectModuleObject::Slot protoSlot) {
static JSObject* DefineMetaTypeDescr(
JSContext* cx, const char* name, Handle<GlobalObject*> global,
Handle<WasmNamespaceObject*> namespaceObject,
WasmNamespaceObject::Slot protoSlot) {
RootedAtom className(cx, Atomize(cx, name, strlen(name)));
if (!className) {
return nullptr;
@ -926,46 +922,27 @@ static JSObject* DefineMetaTypeDescr(JSContext* cx, const char* name,
return nullptr;
}
module->initReservedSlot(protoSlot, ObjectValue(*proto));
namespaceObject->initReservedSlot(protoSlot, ObjectValue(*proto));
return ctor;
}
static JSObject* CreateTypedObjectModuleObject(JSContext* cx, JSProtoKey key) {
Handle<GlobalObject*> global = cx->global();
RootedObject objProto(cx,
GlobalObject::getOrCreateObjectPrototype(cx, global));
if (!objProto) {
return nullptr;
}
return NewSingletonObjectWithGivenProto<TypedObjectModuleObject>(cx,
objProto);
}
/* The initialization strategy for TypedObjects is mildly unusual
* compared to other classes. Because all of the types are members
* of a single global, `TypedObject`, we basically make the
* initializer for the `TypedObject` class populate the
* `TypedObject` global (which is referred to as "module" herein).
*/
static bool TypedObjectModuleObjectClassFinish(JSContext* cx, HandleObject ctor,
HandleObject proto) {
Handle<TypedObjectModuleObject*> module = ctor.as<TypedObjectModuleObject>();
bool js::InitTypedObjectNamespace(
JSContext* cx, Handle<WasmNamespaceObject*> namespaceObject) {
Handle<GlobalObject*> global = cx->global();
// uint8, uint16, any, etc
#define BINARYDATA_SCALAR_DEFINE(constant_, type_, name_) \
if (!DefineSimpleTypeDescr<ScalarTypeDescr>(cx, global, module, constant_, \
cx->names().name_)) \
if (!DefineSimpleTypeDescr<ScalarTypeDescr>(cx, global, namespaceObject, \
constant_, cx->names().name_)) \
return false;
JS_FOR_EACH_SCALAR_TYPE_REPR(BINARYDATA_SCALAR_DEFINE)
#undef BINARYDATA_SCALAR_DEFINE
#define BINARYDATA_REFERENCE_DEFINE(constant_, type_, name_) \
if (!DefineSimpleTypeDescr<ReferenceTypeDescr>( \
cx, global, module, constant_, cx->names().name_)) \
#define BINARYDATA_REFERENCE_DEFINE(constant_, type_, name_) \
if (!DefineSimpleTypeDescr<ReferenceTypeDescr>( \
cx, global, namespaceObject, constant_, cx->names().name_)) \
return false;
JS_FOR_EACH_REFERENCE_TYPE_REPR(BINARYDATA_REFERENCE_DEFINE)
#undef BINARYDATA_REFERENCE_DEFINE
@ -978,49 +955,52 @@ static bool TypedObjectModuleObjectClassFinish(JSContext* cx, HandleObject ctor,
// JS_GetProperty(). The properties themselves will always exist on the
// object.
if (!JS_GetProperty(cx, module, "int32", &typeDescr)) {
if (!JS_GetProperty(cx, namespaceObject, "int32", &typeDescr)) {
return false;
}
module->initReservedSlot(TypedObjectModuleObject::Int32Desc, typeDescr);
namespaceObject->initReservedSlot(WasmNamespaceObject::Int32Desc, typeDescr);
if (!JS_GetProperty(cx, module, "int64", &typeDescr)) {
if (!JS_GetProperty(cx, namespaceObject, "int64", &typeDescr)) {
return false;
}
module->initReservedSlot(TypedObjectModuleObject::Int64Desc, typeDescr);
namespaceObject->initReservedSlot(WasmNamespaceObject::Int64Desc, typeDescr);
if (!JS_GetProperty(cx, module, "float32", &typeDescr)) {
if (!JS_GetProperty(cx, namespaceObject, "float32", &typeDescr)) {
return false;
}
module->initReservedSlot(TypedObjectModuleObject::Float32Desc, typeDescr);
namespaceObject->initReservedSlot(WasmNamespaceObject::Float32Desc,
typeDescr);
if (!JS_GetProperty(cx, module, "float64", &typeDescr)) {
if (!JS_GetProperty(cx, namespaceObject, "float64", &typeDescr)) {
return false;
}
module->initReservedSlot(TypedObjectModuleObject::Float64Desc, typeDescr);
namespaceObject->initReservedSlot(WasmNamespaceObject::Float64Desc,
typeDescr);
if (!JS_GetProperty(cx, module, "Object", &typeDescr)) {
if (!JS_GetProperty(cx, namespaceObject, "Object", &typeDescr)) {
return false;
}
module->initReservedSlot(TypedObjectModuleObject::ObjectDesc, typeDescr);
namespaceObject->initReservedSlot(WasmNamespaceObject::ObjectDesc, typeDescr);
if (!JS_GetProperty(cx, module, "WasmAnyRef", &typeDescr)) {
if (!JS_GetProperty(cx, namespaceObject, "WasmAnyRef", &typeDescr)) {
return false;
}
module->initReservedSlot(TypedObjectModuleObject::WasmAnyRefDesc, typeDescr);
namespaceObject->initReservedSlot(WasmNamespaceObject::WasmAnyRefDesc,
typeDescr);
// ArrayType.
RootedObject arrayType(cx);
arrayType = DefineMetaTypeDescr<ArrayMetaTypeDescr>(
cx, "ArrayType", global, module,
TypedObjectModuleObject::ArrayTypePrototype);
cx, "ArrayType", global, namespaceObject,
WasmNamespaceObject::ArrayTypePrototype);
if (!arrayType) {
return false;
}
RootedValue arrayTypeValue(cx, ObjectValue(*arrayType));
if (!DefineDataProperty(cx, module, cx->names().ArrayType, arrayTypeValue,
JSPROP_READONLY | JSPROP_PERMANENT)) {
if (!DefineDataProperty(cx, namespaceObject, cx->names().ArrayType,
arrayTypeValue, JSPROP_READONLY | JSPROP_PERMANENT)) {
return false;
}
@ -1028,14 +1008,15 @@ static bool TypedObjectModuleObjectClassFinish(JSContext* cx, HandleObject ctor,
RootedObject structType(cx);
structType = DefineMetaTypeDescr<StructMetaTypeDescr>(
cx, "StructType", global, module,
TypedObjectModuleObject::StructTypePrototype);
cx, "StructType", global, namespaceObject,
WasmNamespaceObject::StructTypePrototype);
if (!structType) {
return false;
}
RootedValue structTypeValue(cx, ObjectValue(*structType));
if (!DefineDataProperty(cx, module, cx->names().StructType, structTypeValue,
if (!DefineDataProperty(cx, namespaceObject, cx->names().StructType,
structTypeValue,
JSPROP_READONLY | JSPROP_PERMANENT)) {
return false;
}
@ -1043,15 +1024,6 @@ static bool TypedObjectModuleObjectClassFinish(JSContext* cx, HandleObject ctor,
return true;
}
const ClassSpec TypedObjectModuleObject::classSpec_ = {
CreateTypedObjectModuleObject,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
TypedObjectModuleObjectClassFinish};
TypedProto* TypedProto::create(JSContext* cx) {
Handle<GlobalObject*> global = cx->global();
RootedObject objProto(cx,

View File

@ -20,6 +20,11 @@
namespace js {
class WasmNamespaceObject;
extern bool InitTypedObjectNamespace(
JSContext* cx, Handle<WasmNamespaceObject*> namespaceObject);
/* The prototype for typed objects. */
class TypedProto : public NativeObject {
public:
@ -344,31 +349,6 @@ class StructTypeDescr : public ComplexTypeDescr {
using HandleStructTypeDescr = Handle<StructTypeDescr*>;
/*
* This object exists in order to encapsulate the typed object types
* somewhat, rather than sticking them all into the global object.
* Eventually it will go away and become a module.
*/
class TypedObjectModuleObject : public NativeObject {
public:
enum Slot {
ArrayTypePrototype,
StructTypePrototype,
Int32Desc,
Int64Desc,
Float32Desc,
Float64Desc,
ObjectDesc,
WasmAnyRefDesc,
SlotCount
};
static const JSClass class_;
private:
static const ClassSpec classSpec_;
};
/* Base type for typed objects. */
class TypedObject : public JSObject {
static MOZ_MUST_USE bool obj_getArrayElement(JSContext* cx,

View File

@ -4316,11 +4316,14 @@ static JSObject* CreateWebAssemblyObject(JSContext* cx, JSProtoKey key) {
if (!proto) {
return nullptr;
}
return NewSingletonObjectWithGivenProto(cx, &WebAssemblyClass, proto);
return NewSingletonObjectWithGivenProto(cx, &WasmNamespaceObject::class_,
proto);
}
static bool WebAssemblyClassFinish(JSContext* cx, HandleObject wasm,
static bool WebAssemblyClassFinish(JSContext* cx, HandleObject object,
HandleObject proto) {
Handle<WasmNamespaceObject*> wasm = object.as<WasmNamespaceObject>();
struct NameAndProtoKey {
const char* const name;
JSProtoKey key;
@ -4360,6 +4363,10 @@ static bool WebAssemblyClassFinish(JSContext* cx, HandleObject wasm,
}
}
if (GcTypesAvailable(cx) && !InitTypedObjectNamespace(cx, wasm)) {
return false;
}
return true;
}
@ -4371,6 +4378,8 @@ static const ClassSpec WebAssemblyClassSpec = {CreateWebAssemblyObject,
nullptr,
WebAssemblyClassFinish};
const JSClass js::WebAssemblyClass = {
js_WebAssembly_str, JSCLASS_HAS_CACHED_PROTO(JSProto_WebAssembly),
const JSClass js::WasmNamespaceObject::class_ = {
js_WebAssembly_str,
JSCLASS_HAS_RESERVED_SLOTS(SlotCount) |
JSCLASS_HAS_CACHED_PROTO(JSProto_WebAssembly),
JS_NULL_CLASS_OPS, &WebAssemblyClassSpec};

View File

@ -184,10 +184,6 @@ MOZ_MUST_USE bool CheckRefType(JSContext* cx, RefType targetType, HandleValue v,
} // namespace wasm
// The class of the WebAssembly global namespace object.
extern const JSClass WebAssemblyClass;
// The class of WebAssembly.Module. Each WasmModuleObject owns a
// wasm::Module. These objects are used both as content-facing JS objects and as
// internal implementation details of asm.js.
@ -457,6 +453,28 @@ class WasmTableObject : public NativeObject {
wasm::Table& table() const;
};
// The class of the WebAssembly global namespace object.
class WasmNamespaceObject : public NativeObject {
public:
enum Slot {
ArrayTypePrototype,
StructTypePrototype,
Int32Desc,
Int64Desc,
Float32Desc,
Float64Desc,
ObjectDesc,
WasmAnyRefDesc,
SlotCount
};
static const JSClass class_;
private:
static const ClassSpec classSpec_;
};
} // namespace js
#endif // wasm_js_h

View File

@ -1244,23 +1244,18 @@ bool Module::makeStructTypeDescrs(
MOZ_CRASH("Should not have seen any struct types");
#else
# ifndef JS_HAS_TYPED_OBJECTS
# error "GC types require TypedObject"
# endif
// Not just any prototype object will do, we must have the actual
// StructTypePrototype.
RootedObject typedObjectModule(
cx, GlobalObject::getOrCreateTypedObjectModule(cx, cx->global()));
if (!typedObjectModule) {
RootedObject namespaceObject(
cx, GlobalObject::getOrCreateWebAssemblyNamespace(cx, cx->global()));
if (!namespaceObject) {
return false;
}
RootedNativeObject toModule(cx, &typedObjectModule->as<NativeObject>());
RootedNativeObject toModule(cx, &namespaceObject->as<NativeObject>());
RootedObject prototype(
cx,
&toModule->getReservedSlot(TypedObjectModuleObject::StructTypePrototype)
.toObject());
cx, &toModule->getReservedSlot(WasmNamespaceObject::StructTypePrototype)
.toObject());
for (const StructType& structType : structTypes()) {
RootedIdVector ids(cx);