Implement globalThis.
parent
d8a7e12637
commit
0d09fdfba3
|
@ -779,7 +779,7 @@ struct JSClass {
|
||||||
// application.
|
// application.
|
||||||
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
|
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
|
||||||
#define JSCLASS_GLOBAL_SLOT_COUNT \
|
#define JSCLASS_GLOBAL_SLOT_COUNT \
|
||||||
(JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 45)
|
(JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 46)
|
||||||
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
|
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
|
||||||
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
|
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
|
||||||
#define JSCLASS_GLOBAL_FLAGS \
|
#define JSCLASS_GLOBAL_FLAGS \
|
||||||
|
|
|
@ -1029,13 +1029,17 @@ JS_ResolveStandardClass(JSContext* cx, HandleObject obj, HandleId id, bool* reso
|
||||||
|
|
||||||
/* Check whether we're resolving 'undefined', and define it if so. */
|
/* Check whether we're resolving 'undefined', and define it if so. */
|
||||||
JSAtom* idAtom = JSID_TO_ATOM(id);
|
JSAtom* idAtom = JSID_TO_ATOM(id);
|
||||||
JSAtom* undefinedAtom = cx->names().undefined;
|
if (idAtom == cx->names().undefined) {
|
||||||
if (idAtom == undefinedAtom) {
|
|
||||||
*resolved = true;
|
*resolved = true;
|
||||||
return DefineProperty(cx, global, id, UndefinedHandleValue, nullptr, nullptr,
|
return DefineProperty(cx, global, id, UndefinedHandleValue, nullptr, nullptr,
|
||||||
JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING);
|
JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve a "globalThis" self-referential property if necessary.
|
||||||
|
if (idAtom == cx->names().globalThis) {
|
||||||
|
return GlobalObject::maybeResolveGlobalThis(cx, global, resolved);
|
||||||
|
}
|
||||||
|
|
||||||
/* Try for class constructors/prototypes named by well-known atoms. */
|
/* Try for class constructors/prototypes named by well-known atoms. */
|
||||||
stdnm = LookupStdName(cx->names(), idAtom, standard_class_names);
|
stdnm = LookupStdName(cx->names(), idAtom, standard_class_names);
|
||||||
|
|
||||||
|
@ -1088,6 +1092,7 @@ JS_MayResolveStandardClass(const JSAtomState& names, jsid id, JSObject* maybeObj
|
||||||
// better, we need a JSContext here; it's fine as it is.)
|
// better, we need a JSContext here; it's fine as it is.)
|
||||||
|
|
||||||
return atom == names.undefined ||
|
return atom == names.undefined ||
|
||||||
|
atom == names.globalThis ||
|
||||||
LookupStdName(names, atom, standard_class_names) ||
|
LookupStdName(names, atom, standard_class_names) ||
|
||||||
LookupStdName(names, atom, builtin_property_names);
|
LookupStdName(names, atom, builtin_property_names);
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,6 +160,7 @@
|
||||||
macro(getPropertyDescriptor, getPropertyDescriptor, "getPropertyDescriptor") \
|
macro(getPropertyDescriptor, getPropertyDescriptor, "getPropertyDescriptor") \
|
||||||
macro(getPrototypeOf, getPrototypeOf, "getPrototypeOf") \
|
macro(getPrototypeOf, getPrototypeOf, "getPrototypeOf") \
|
||||||
macro(global, global, "global") \
|
macro(global, global, "global") \
|
||||||
|
macro(globalThis, globalThis, "globalThis") \
|
||||||
macro(Handle, Handle, "Handle") \
|
macro(Handle, Handle, "Handle") \
|
||||||
macro(has, has, "has") \
|
macro(has, has, "has") \
|
||||||
macro(hasOwn, hasOwn, "hasOwn") \
|
macro(hasOwn, hasOwn, "hasOwn") \
|
||||||
|
|
|
@ -296,6 +296,32 @@ GlobalObject::initBuiltinConstructor(JSContext* cx, Handle<GlobalObject*> global
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve a "globalThis" self-referential property if necessary,
|
||||||
|
// per a stage-3 proposal. https://github.com/tc39/ecma262/pull/702
|
||||||
|
//
|
||||||
|
// We could also do this in |FinishObjectClassInit| to trim the global
|
||||||
|
// resolve hook. Unfortunately, |ToWindowProxyIfWindow| doesn't work then:
|
||||||
|
// the browser's |nsGlobalWindow::SetNewDocument| invokes Object init
|
||||||
|
// *before* it sets the global's WindowProxy using |js::SetWindowProxy|.
|
||||||
|
//
|
||||||
|
// Refactoring global object creation code to support this approach is a
|
||||||
|
// challenge for another day.
|
||||||
|
/* static */ bool
|
||||||
|
GlobalObject::maybeResolveGlobalThis(JSContext* cx, Handle<GlobalObject*> global, bool* resolved)
|
||||||
|
{
|
||||||
|
if (global->getSlot(GLOBAL_THIS_RESOLVED).isUndefined()) {
|
||||||
|
RootedValue v(cx, ObjectValue(*ToWindowProxyIfWindow(global)));
|
||||||
|
if (!DefineProperty(cx, global, cx->names().globalThis, v, nullptr, nullptr, JSPROP_RESOLVING)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*resolved = true;
|
||||||
|
global->setSlot(GLOBAL_THIS_RESOLVED, BooleanValue(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
GlobalObject*
|
GlobalObject*
|
||||||
GlobalObject::createInternal(JSContext* cx, const Class* clasp)
|
GlobalObject::createInternal(JSContext* cx, const Class* clasp)
|
||||||
{
|
{
|
||||||
|
@ -419,6 +445,12 @@ GlobalObject::initStandardClasses(JSContext* cx, Handle<GlobalObject*> global)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve a "globalThis" self-referential property if necessary.
|
||||||
|
bool resolved;
|
||||||
|
if (!GlobalObject::maybeResolveGlobalThis(cx, global, &resolved)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t k = 0; k < JSProto_LIMIT; ++k) {
|
for (size_t k = 0; k < JSProto_LIMIT; ++k) {
|
||||||
if (!ensureConstructor(cx, global, static_cast<JSProtoKey>(k)))
|
if (!ensureConstructor(cx, global, static_cast<JSProtoKey>(k)))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -121,6 +121,7 @@ class GlobalObject : public NativeObject
|
||||||
FOR_OF_PIC_CHAIN,
|
FOR_OF_PIC_CHAIN,
|
||||||
MODULE_RESOLVE_HOOK,
|
MODULE_RESOLVE_HOOK,
|
||||||
WINDOW_PROXY,
|
WINDOW_PROXY,
|
||||||
|
GLOBAL_THIS_RESOLVED,
|
||||||
|
|
||||||
/* Total reserved-slot count for global objects. */
|
/* Total reserved-slot count for global objects. */
|
||||||
RESERVED_SLOTS
|
RESERVED_SLOTS
|
||||||
|
@ -171,6 +172,8 @@ class GlobalObject : public NativeObject
|
||||||
static bool initBuiltinConstructor(JSContext* cx, Handle<GlobalObject*> global,
|
static bool initBuiltinConstructor(JSContext* cx, Handle<GlobalObject*> global,
|
||||||
JSProtoKey key, HandleObject ctor, HandleObject proto);
|
JSProtoKey key, HandleObject ctor, HandleObject proto);
|
||||||
|
|
||||||
|
static bool maybeResolveGlobalThis(JSContext* cx, Handle<GlobalObject*> global, bool* resolved);
|
||||||
|
|
||||||
void setConstructor(JSProtoKey key, const Value& v) {
|
void setConstructor(JSProtoKey key, const Value& v) {
|
||||||
MOZ_ASSERT(key <= JSProto_LIMIT);
|
MOZ_ASSERT(key <= JSProto_LIMIT);
|
||||||
setSlot(APPLICATION_SLOTS + key, v);
|
setSlot(APPLICATION_SLOTS + key, v);
|
||||||
|
|
Loading…
Reference in New Issue