зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1370608 part 2 - Add JS_NewEnumerateStandardClasses and use it in js/src. r=evilpie
This commit is contained in:
Родитель
83f290de99
Коммит
1a863117ff
|
@ -7,12 +7,6 @@
|
|||
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
||||
static bool
|
||||
GlobalEnumerate(JSContext* cx, JS::Handle<JSObject*> obj)
|
||||
{
|
||||
return JS_EnumerateStandardClasses(cx, obj);
|
||||
}
|
||||
|
||||
static bool
|
||||
GlobalResolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp)
|
||||
{
|
||||
|
@ -23,7 +17,7 @@ BEGIN_TEST(testRedefineGlobalEval)
|
|||
{
|
||||
static const JSClassOps clsOps = {
|
||||
nullptr, nullptr, nullptr, nullptr,
|
||||
GlobalEnumerate, nullptr, GlobalResolve, nullptr, nullptr,
|
||||
nullptr, JS_NewEnumerateStandardClasses, GlobalResolve, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr,
|
||||
JS_GlobalObjectTraceHook
|
||||
};
|
||||
|
|
|
@ -1117,6 +1117,63 @@ JS_EnumerateStandardClasses(JSContext* cx, HandleObject obj)
|
|||
return GlobalObject::initStandardClasses(cx, global);
|
||||
}
|
||||
|
||||
static bool
|
||||
EnumerateUnresolvedStandardClasses(JSContext* cx, Handle<GlobalObject*> global,
|
||||
AutoIdVector& properties, const JSStdName* table)
|
||||
{
|
||||
for (unsigned i = 0; !table[i].isSentinel(); i++) {
|
||||
if (table[i].isDummy())
|
||||
continue;
|
||||
|
||||
JSProtoKey key = table[i].key;
|
||||
|
||||
// If the standard class has been resolved, the properties have been
|
||||
// defined on the global so we don't need to add them here.
|
||||
if (global->isStandardClassResolved(key))
|
||||
continue;
|
||||
|
||||
if (GlobalObject::skipDeselectedConstructor(cx, key))
|
||||
continue;
|
||||
|
||||
if (const Class* clasp = ProtoKeyToClass(key)) {
|
||||
if (clasp->flags & JSCLASS_IS_ANONYMOUS)
|
||||
continue;
|
||||
if (!clasp->specShouldDefineConstructor())
|
||||
continue;
|
||||
}
|
||||
|
||||
jsid id = NameToId(AtomStateOffsetToName(cx->names(), table[i].atomOffset));
|
||||
if (!properties.append(id))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_NewEnumerateStandardClasses(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties,
|
||||
bool enumerableOnly)
|
||||
{
|
||||
if (enumerableOnly) {
|
||||
// There are no enumerable lazy properties.
|
||||
return true;
|
||||
}
|
||||
|
||||
Handle<GlobalObject*> global = obj.as<GlobalObject>();
|
||||
|
||||
// It's fine to always append |undefined| here, it's non-configurable and
|
||||
// the enumeration code filters duplicates.
|
||||
if (!properties.append(NameToId(cx->names().undefined)))
|
||||
return false;
|
||||
|
||||
if (!EnumerateUnresolvedStandardClasses(cx, global, properties, standard_class_names))
|
||||
return false;
|
||||
if (!EnumerateUnresolvedStandardClasses(cx, global, properties, builtin_property_names))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_GetClassObject(JSContext* cx, JSProtoKey key, MutableHandleObject objp)
|
||||
{
|
||||
|
|
|
@ -1494,9 +1494,10 @@ JS_InitStandardClasses(JSContext* cx, JS::Handle<JSObject*> obj);
|
|||
* as usual for bool result-typed API entry points.
|
||||
*
|
||||
* This API can be called directly from a global object class's resolve op,
|
||||
* to define standard classes lazily. The class's enumerate op should call
|
||||
* JS_EnumerateStandardClasses(cx, obj), to define eagerly during for..in
|
||||
* loops any classes not yet resolved lazily.
|
||||
* to define standard classes lazily. The class should either have an enumerate
|
||||
* hook that calls JS_EnumerateStandardClasses, or a newEnumerate hook that
|
||||
* calls JS_NewEnumerateStandardClasses. newEnumerate is preferred because it's
|
||||
* faster (does not define all standard classes).
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_ResolveStandardClass(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolved);
|
||||
|
@ -1507,6 +1508,10 @@ JS_MayResolveStandardClass(const JSAtomState& names, jsid id, JSObject* maybeObj
|
|||
extern JS_PUBLIC_API(bool)
|
||||
JS_EnumerateStandardClasses(JSContext* cx, JS::HandleObject obj);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_NewEnumerateStandardClasses(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties,
|
||||
bool enumerableOnly);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_GetClassObject(JSContext* cx, JSProtoKey key, JS::MutableHandle<JSObject*> objp);
|
||||
|
||||
|
|
|
@ -2769,10 +2769,24 @@ js::PreventExtensions(JSContext* cx, HandleObject obj, ObjectOpResult& result, I
|
|||
|
||||
// Force lazy properties to be resolved.
|
||||
if (obj->isNative()) {
|
||||
if (JSEnumerateOp enumerate = obj->getClass()->getEnumerate()) {
|
||||
const Class* clasp = obj->getClass();
|
||||
if (JSEnumerateOp enumerate = clasp->getEnumerate()) {
|
||||
if (!enumerate(cx, obj.as<NativeObject>()))
|
||||
return false;
|
||||
}
|
||||
if (clasp->getNewEnumerate() && clasp->getResolve()) {
|
||||
AutoIdVector properties(cx);
|
||||
if (!clasp->getNewEnumerate()(cx, obj, properties, /* enumerableOnly = */ false))
|
||||
return false;
|
||||
|
||||
RootedId id(cx);
|
||||
for (size_t i = 0; i < properties.length(); i++) {
|
||||
id = properties[i];
|
||||
bool found;
|
||||
if (!HasOwnProperty(cx, obj, id, &found))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sparsify dense elements, to make sure no element can be added without a
|
||||
|
|
|
@ -3068,7 +3068,8 @@ typedef struct ComplexObject {
|
|||
} ComplexObject;
|
||||
|
||||
static bool
|
||||
sandbox_enumerate(JSContext* cx, HandleObject obj)
|
||||
sandbox_enumerate(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties,
|
||||
bool enumerableOnly)
|
||||
{
|
||||
RootedValue v(cx);
|
||||
|
||||
|
@ -3078,7 +3079,7 @@ sandbox_enumerate(JSContext* cx, HandleObject obj)
|
|||
if (!ToBoolean(v))
|
||||
return true;
|
||||
|
||||
return JS_EnumerateStandardClasses(cx, obj);
|
||||
return JS_NewEnumerateStandardClasses(cx, obj, properties, enumerableOnly);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -3095,7 +3096,7 @@ sandbox_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp)
|
|||
|
||||
static const JSClassOps sandbox_classOps = {
|
||||
nullptr, nullptr, nullptr, nullptr,
|
||||
sandbox_enumerate, nullptr, sandbox_resolve,
|
||||
nullptr, sandbox_enumerate, sandbox_resolve,
|
||||
nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr,
|
||||
JS_GlobalObjectTraceHook
|
||||
|
@ -7016,10 +7017,11 @@ js::shell::WarningReporter(JSContext* cx, JSErrorReport* report)
|
|||
}
|
||||
|
||||
static bool
|
||||
global_enumerate(JSContext* cx, HandleObject obj)
|
||||
global_enumerate(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties,
|
||||
bool enumerableOnly)
|
||||
{
|
||||
#ifdef LAZY_STANDARD_CLASSES
|
||||
return JS_EnumerateStandardClasses(cx, obj);
|
||||
return JS_NewEnumerateStandardClasses(cx, obj, properties, enumerableOnly);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
@ -7043,7 +7045,7 @@ global_mayResolve(const JSAtomState& names, jsid id, JSObject* maybeObj)
|
|||
|
||||
static const JSClassOps global_classOps = {
|
||||
nullptr, nullptr, nullptr, nullptr,
|
||||
global_enumerate, nullptr, global_resolve, global_mayResolve,
|
||||
nullptr, global_enumerate, global_resolve, global_mayResolve,
|
||||
nullptr,
|
||||
nullptr, nullptr, nullptr,
|
||||
JS_GlobalObjectTraceHook
|
||||
|
|
Загрузка…
Ссылка в новой задаче