Bug 1396482 part 1. Add an API for enumerating all the standard class names on a global. r=jandem
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 28 Sep 2018 10:49:44 -0400
changeset 494545 2396739f4dfc27bf3ede8055aa637fdf2501ea6c
parent 494544 522b47a9ae93d9959915f148345ff8ec852341ea
child 494546 74728687904930fe904b02764727adfdb97b6be2
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 {