зеркало из 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"
|
#include "jsapi-tests/tests.h"
|
||||||
|
|
||||||
static bool
|
|
||||||
GlobalEnumerate(JSContext* cx, JS::Handle<JSObject*> obj)
|
|
||||||
{
|
|
||||||
return JS_EnumerateStandardClasses(cx, obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
GlobalResolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp)
|
GlobalResolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp)
|
||||||
{
|
{
|
||||||
|
@ -23,7 +17,7 @@ BEGIN_TEST(testRedefineGlobalEval)
|
||||||
{
|
{
|
||||||
static const JSClassOps clsOps = {
|
static const JSClassOps clsOps = {
|
||||||
nullptr, nullptr, nullptr, nullptr,
|
nullptr, nullptr, nullptr, nullptr,
|
||||||
GlobalEnumerate, nullptr, GlobalResolve, nullptr, nullptr,
|
nullptr, JS_NewEnumerateStandardClasses, GlobalResolve, nullptr, nullptr,
|
||||||
nullptr, nullptr, nullptr,
|
nullptr, nullptr, nullptr,
|
||||||
JS_GlobalObjectTraceHook
|
JS_GlobalObjectTraceHook
|
||||||
};
|
};
|
||||||
|
|
|
@ -1117,6 +1117,63 @@ JS_EnumerateStandardClasses(JSContext* cx, HandleObject obj)
|
||||||
return GlobalObject::initStandardClasses(cx, global);
|
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_PUBLIC_API(bool)
|
||||||
JS_GetClassObject(JSContext* cx, JSProtoKey key, MutableHandleObject objp)
|
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.
|
* as usual for bool result-typed API entry points.
|
||||||
*
|
*
|
||||||
* This API can be called directly from a global object class's resolve op,
|
* 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
|
* to define standard classes lazily. The class should either have an enumerate
|
||||||
* JS_EnumerateStandardClasses(cx, obj), to define eagerly during for..in
|
* hook that calls JS_EnumerateStandardClasses, or a newEnumerate hook that
|
||||||
* loops any classes not yet resolved lazily.
|
* calls JS_NewEnumerateStandardClasses. newEnumerate is preferred because it's
|
||||||
|
* faster (does not define all standard classes).
|
||||||
*/
|
*/
|
||||||
extern JS_PUBLIC_API(bool)
|
extern JS_PUBLIC_API(bool)
|
||||||
JS_ResolveStandardClass(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolved);
|
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)
|
extern JS_PUBLIC_API(bool)
|
||||||
JS_EnumerateStandardClasses(JSContext* cx, JS::HandleObject obj);
|
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)
|
extern JS_PUBLIC_API(bool)
|
||||||
JS_GetClassObject(JSContext* cx, JSProtoKey key, JS::MutableHandle<JSObject*> objp);
|
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.
|
// Force lazy properties to be resolved.
|
||||||
if (obj->isNative()) {
|
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>()))
|
if (!enumerate(cx, obj.as<NativeObject>()))
|
||||||
return false;
|
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
|
// Sparsify dense elements, to make sure no element can be added without a
|
||||||
|
|
|
@ -3068,7 +3068,8 @@ typedef struct ComplexObject {
|
||||||
} ComplexObject;
|
} ComplexObject;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
sandbox_enumerate(JSContext* cx, HandleObject obj)
|
sandbox_enumerate(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties,
|
||||||
|
bool enumerableOnly)
|
||||||
{
|
{
|
||||||
RootedValue v(cx);
|
RootedValue v(cx);
|
||||||
|
|
||||||
|
@ -3078,7 +3079,7 @@ sandbox_enumerate(JSContext* cx, HandleObject obj)
|
||||||
if (!ToBoolean(v))
|
if (!ToBoolean(v))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return JS_EnumerateStandardClasses(cx, obj);
|
return JS_NewEnumerateStandardClasses(cx, obj, properties, enumerableOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -3095,7 +3096,7 @@ sandbox_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp)
|
||||||
|
|
||||||
static const JSClassOps sandbox_classOps = {
|
static const JSClassOps sandbox_classOps = {
|
||||||
nullptr, nullptr, nullptr, nullptr,
|
nullptr, nullptr, nullptr, nullptr,
|
||||||
sandbox_enumerate, nullptr, sandbox_resolve,
|
nullptr, sandbox_enumerate, sandbox_resolve,
|
||||||
nullptr, nullptr,
|
nullptr, nullptr,
|
||||||
nullptr, nullptr, nullptr,
|
nullptr, nullptr, nullptr,
|
||||||
JS_GlobalObjectTraceHook
|
JS_GlobalObjectTraceHook
|
||||||
|
@ -7016,10 +7017,11 @@ js::shell::WarningReporter(JSContext* cx, JSErrorReport* report)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
global_enumerate(JSContext* cx, HandleObject obj)
|
global_enumerate(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties,
|
||||||
|
bool enumerableOnly)
|
||||||
{
|
{
|
||||||
#ifdef LAZY_STANDARD_CLASSES
|
#ifdef LAZY_STANDARD_CLASSES
|
||||||
return JS_EnumerateStandardClasses(cx, obj);
|
return JS_NewEnumerateStandardClasses(cx, obj, properties, enumerableOnly);
|
||||||
#else
|
#else
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
@ -7043,7 +7045,7 @@ global_mayResolve(const JSAtomState& names, jsid id, JSObject* maybeObj)
|
||||||
|
|
||||||
static const JSClassOps global_classOps = {
|
static const JSClassOps global_classOps = {
|
||||||
nullptr, nullptr, nullptr, nullptr,
|
nullptr, nullptr, nullptr, nullptr,
|
||||||
global_enumerate, nullptr, global_resolve, global_mayResolve,
|
nullptr, global_enumerate, global_resolve, global_mayResolve,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr, nullptr, nullptr,
|
nullptr, nullptr, nullptr,
|
||||||
JS_GlobalObjectTraceHook
|
JS_GlobalObjectTraceHook
|
||||||
|
|
Загрузка…
Ссылка в новой задаче