Bug 1396482 part 1. Add an API for enumerating all the standard class names on a global. r=jandem
☠☠ backed out by 59496d591584 ☠ ☠
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 28 Sep 2018 10:49:44 -0400
changeset 494474 c23086c123932c3e3ae24a39285ccad83bc03a99
parent 494473 634a0cbc28afb52e0a8f4f7088e82fb25901f9d1
child 494475 8c9b27320d6e37b77631980d19607d5c58717896
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1396482
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1396482 part 1. Add an API for enumerating all the standard class names on a global. r=jandem
js/src/jsapi.cpp
js/src/jsapi.h
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1086,29 +1086,30 @@ JS_EnumerateStandardClasses(JSContext* c
     AssertHeapIsIdle();
     CHECK_THREAD(cx);
     cx->check(obj);
     Handle<GlobalObject*> global = obj.as<GlobalObject>();
     return GlobalObject::initStandardClasses(cx, global);
 }
 
 static bool
-EnumerateUnresolvedStandardClasses(JSContext* cx, Handle<GlobalObject*> global,
-                                   AutoIdVector& properties, const JSStdName* table)
+EnumerateStandardClassesInTable(JSContext* cx, Handle<GlobalObject*> global,
+                                AutoIdVector& properties, const JSStdName* table,
+                                bool includeResolved)
 {
     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)) {
+        if (!includeResolved && global->isStandardClassResolved(key)) {
             continue;
         }
 
         if (GlobalObject::skipDeselectedConstructor(cx, key)) {
             continue;
         }
 
         if (const Class* clasp = ProtoKeyToClass(key)) {
@@ -1124,44 +1125,62 @@ EnumerateUnresolvedStandardClasses(JSCon
         if (!properties.append(id)) {
             return false;
         }
     }
 
     return true;
 }
 
-JS_PUBLIC_API(bool)
-JS_NewEnumerateStandardClasses(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties,
-                               bool enumerableOnly)
+static bool
+EnumerateStandardClasses(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties,
+                         bool enumerableOnly, bool includeResolved)
 {
     if (enumerableOnly) {
-        // There are no enumerable lazy properties.
+        // There are no enumerable standard classes and "undefined" is
+        // not enumerable.
         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)) {
+    if (!EnumerateStandardClassesInTable(cx, global, properties, standard_class_names,
+                                         includeResolved)) {
         return false;
     }
-    if (!EnumerateUnresolvedStandardClasses(cx, global, properties, builtin_property_names)) {
+    if (!EnumerateStandardClassesInTable(cx, global, properties, builtin_property_names,
+                                         includeResolved)) {
         return false;
     }
 
     return true;
 }
 
 JS_PUBLIC_API(bool)
+JS_NewEnumerateStandardClasses(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties,
+                               bool enumerableOnly)
+{
+    return EnumerateStandardClasses(cx, obj, properties, enumerableOnly, false);
+}
+
+JS_PUBLIC_API(bool)
+JS_NewEnumerateStandardClassesIncludingResolved(JSContext* cx, JS::HandleObject obj,
+                                                JS::AutoIdVector& properties,
+                                                bool enumerableOnly)
+{
+    return EnumerateStandardClasses(cx, obj, properties, enumerableOnly, true);
+}
+
+JS_PUBLIC_API(bool)
 JS_GetClassObject(JSContext* cx, JSProtoKey key, MutableHandleObject objp)
 {
     AssertHeapIsIdle();
     CHECK_THREAD(cx);
     JSObject* obj = GlobalObject::getOrCreateConstructor(cx, key);
     if (!obj) {
         return false;
     }
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -952,20 +952,37 @@ extern JS_PUBLIC_API(bool)
 JS_ResolveStandardClass(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolved);
 
 extern JS_PUBLIC_API(bool)
 JS_MayResolveStandardClass(const JSAtomState& names, jsid id, JSObject* maybeObj);
 
 extern JS_PUBLIC_API(bool)
 JS_EnumerateStandardClasses(JSContext* cx, JS::HandleObject obj);
 
+/**
+ * Fill "properties" with a list of standard class names that have not yet been
+ * resolved on "obj".  This can be used as (part of) a newEnumerate class hook on a
+ * global.  Already-resolved things are excluded because they might have been deleted
+ * by script after being resolved and enumeration considers already-defined
+ * properties anyway.
+ */
 extern JS_PUBLIC_API(bool)
 JS_NewEnumerateStandardClasses(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties,
                                bool enumerableOnly);
 
+/**
+ * Fill "properties" with a list of standard class names.  This can be used for
+ * proxies that want to define behavior that looks like enumerating a global without
+ * touching the global itself.
+ */
+extern JS_PUBLIC_API(bool)
+JS_NewEnumerateStandardClassesIncludingResolved(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);
 
 extern JS_PUBLIC_API(bool)
 JS_GetClassPrototype(JSContext* cx, JSProtoKey key, JS::MutableHandle<JSObject*> objp);
 
 namespace JS {