[gjs/wip/ptomato/mayresolve: 31/31] WIP - js: Use mayResolve hook to avoid unnecessary lookups



commit 3fd846c0ec5e0993a008c1e0eabd008c38c1adaf
Author: Philip Chimento <philip chimento gmail com>
Date:   Sun Apr 23 21:24:35 2017 -0700

    WIP - js: Use mayResolve hook to avoid unnecessary lookups
    
    Does not work.

 gi/boxed.cpp                |   15 ++++++++++++++-
 gi/fundamental.cpp          |   15 ++++++++++++++-
 gi/interface.cpp            |    2 +-
 gi/object.cpp               |   19 ++++++++++++++++++-
 gi/param.cpp                |    2 +-
 gi/repo.cpp                 |   24 +++++++++++++++---------
 gi/union.cpp                |   15 ++++++++++++++-
 gjs/importer.cpp            |    6 +++---
 gjs/jsapi-class.h           |    4 ++++
 gjs/jsapi-dynamic-class.cpp |   30 ++++++++++++++++++++++++++++++
 10 files changed, 114 insertions(+), 18 deletions(-)
---
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index f5fd4bc..e86c5e3 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -189,6 +189,19 @@ boxed_resolve(JSContext       *context,
     return true;
 }
 
+static bool
+boxed_may_resolve(const JSAtomState& names,
+                  jsid               id,
+                  JSObject          *maybe_obj)
+{
+    if (!JSID_IS_STRING(id))
+        return false;
+    JSFlatString *str = JSID_TO_FLAT_STRING(id);
+    return !(JS_FlatStringEqualsAscii(str, "constructor") ||
+             JS_FlatStringEqualsAscii(str, "prototype") ||
+             JS_FlatStringEqualsAscii(str, "toString"));
+}
+
 /* Check to see if JS::Value passed in is another Boxed object of the same,
  * and if so, retrieves the Boxed private structure for it.
  */
@@ -940,7 +953,7 @@ struct JSClass gjs_boxed_class = {
     NULL,  /* setProperty */
     NULL,  /* enumerate */
     boxed_resolve,
-    nullptr,  /* mayResolve */
+    boxed_may_resolve,
     boxed_finalize,
     NULL,  /* call */
     NULL,  /* hasInstance */
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index 677fd65..eee417f 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -389,6 +389,19 @@ fundamental_instance_resolve(JSContext       *context,
 }
 
 static bool
+fundamental_instance_may_resolve(const JSAtomState& names,
+                                 jsid               id,
+                                 JSObject          *maybe_obj)
+{
+    if (!JSID_IS_STRING(id))
+        return false;
+    JSFlatString *str = JSID_TO_FLAT_STRING(id);
+    return !(JS_FlatStringEqualsAscii(str, "constructor") ||
+             JS_FlatStringEqualsAscii(str, "prototype") ||
+             JS_FlatStringEqualsAscii(str, "toString"));
+}
+
+static bool
 fundamental_invoke_constructor(FundamentalInstance        *priv,
                                JSContext                  *context,
                                JS::HandleObject            obj,
@@ -564,7 +577,7 @@ struct JSClass gjs_fundamental_instance_class = {
     NULL,  /* setProperty */
     NULL,  /* enumerate */
     fundamental_instance_resolve,
-    nullptr,  /* mayResolve */
+    fundamental_instance_may_resolve,
     fundamental_finalize,
     NULL,  /* call */
     NULL,  /* hasInstance */
diff --git a/gi/interface.cpp b/gi/interface.cpp
index b1f9647..f5cfb85 100644
--- a/gi/interface.cpp
+++ b/gi/interface.cpp
@@ -172,7 +172,7 @@ struct JSClass gjs_interface_class = {
     NULL,  /* setProperty */
     NULL,  /* enumerate */
     interface_resolve,
-    nullptr,  /* mayResolve */
+    gjs_dynamic_class_default_may_resolve,
     interface_finalize
 };
 
diff --git a/gi/object.cpp b/gi/object.cpp
index ddcf1d7..87c59fd 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -818,6 +818,23 @@ object_instance_resolve(JSContext       *context,
     return true;
 }
 
+static bool
+object_instance_may_resolve(const JSAtomState& names,
+                            jsid               id,
+                            JSObject          *maybe_obj)
+{
+    if (!JSID_IS_STRING(id))
+        return false;
+    JSFlatString *str = JSID_TO_FLAT_STRING(id);
+    return !(JS_FlatStringEqualsAscii(str, "_init") ||
+             JS_FlatStringEqualsAscii(str, "conntect") ||
+             JS_FlatStringEqualsAscii(str, "connectAfter") ||
+             JS_FlatStringEqualsAscii(str, "emit") ||
+             JS_FlatStringEqualsAscii(str, "constructor") ||
+             JS_FlatStringEqualsAscii(str, "prototype") ||
+             JS_FlatStringEqualsAscii(str, "toString"));
+}
+
 static void
 free_g_params(GParameter *params,
               int         n_params)
@@ -1815,7 +1832,7 @@ struct JSClass gjs_object_instance_class = {
     object_instance_set_prop,
     NULL,  /* enumerate */
     object_instance_resolve,
-    nullptr,  /* mayResolve */
+    object_instance_may_resolve,
     object_instance_finalize,
     NULL,
     NULL,
diff --git a/gi/param.cpp b/gi/param.cpp
index d2e6e5a..9e0dbac 100644
--- a/gi/param.cpp
+++ b/gi/param.cpp
@@ -154,7 +154,7 @@ struct JSClass gjs_param_class = {
     NULL,  /* setProperty */
     NULL,  /* enumerate */
     param_resolve,
-    nullptr,  /* mayResolve */
+    gjs_dynamic_class_default_may_resolve,
     param_finalize
 };
 
diff --git a/gi/repo.cpp b/gi/repo.cpp
index cdc5064..17b3666 100644
--- a/gi/repo.cpp
+++ b/gi/repo.cpp
@@ -174,14 +174,6 @@ repo_resolve(JSContext       *context,
         return true; /* not resolved, but no error */
     }
 
-    /* let Object.prototype resolve these */
-    if (strcmp(name, "valueOf") == 0 ||
-        strcmp(name, "toString") == 0) {
-        *resolved = false;
-        g_free(name);
-        return true;
-    }
-
     priv = priv_from_js(context, obj);
     gjs_debug_jsprop(GJS_DEBUG_GREPO, "Resolve prop '%s' hook obj %p priv %p",
                      name, obj.get(), priv);
@@ -203,6 +195,20 @@ repo_resolve(JSContext       *context,
     return true;
 }
 
+static bool
+repo_may_resolve(const JSAtomState& names,
+                 jsid               id,
+                 JSObject          *maybe_obj)
+{
+    if (!JSID_IS_STRING(id))
+        return false;
+    JSFlatString *str = JSID_TO_FLAT_STRING(id);
+    return !(JS_FlatStringEqualsAscii(str, "versions") ||
+             JS_FlatStringEqualsAscii(str, "valueOf") ||
+             JS_FlatStringEqualsAscii(str, "toString") ||
+             JS_FlatStringEqualsAscii(str, "__gjsPrivateNS"));
+}
+
 GJS_NATIVE_CONSTRUCTOR_DEFINE_ABSTRACT(repo)
 
 static void
@@ -234,7 +240,7 @@ struct JSClass gjs_repo_class = {
     NULL,  /* setProperty */
     NULL,  /* enumerate */
     repo_resolve,
-    nullptr,  /* mayResolve */
+    repo_may_resolve,
     repo_finalize
 };
 
diff --git a/gi/union.cpp b/gi/union.cpp
index 8823b91..9f1f6a8 100644
--- a/gi/union.cpp
+++ b/gi/union.cpp
@@ -134,6 +134,19 @@ union_resolve(JSContext       *context,
     return true;
 }
 
+static bool
+union_may_resolve(const JSAtomState& names,
+                  jsid               id,
+                  JSObject          *maybe_obj)
+{
+    if (!JSID_IS_STRING(id))
+        return false;
+    JSFlatString *str = JSID_TO_FLAT_STRING(id);
+    return !(JS_FlatStringEqualsAscii(str, "constructor") ||
+             JS_FlatStringEqualsAscii(str, "prototype") ||
+             JS_FlatStringEqualsAscii(str, "toString"));
+}
+
 static void*
 union_new(JSContext       *context,
           JS::HandleObject obj, /* "this" for constructor */
@@ -301,7 +314,7 @@ struct JSClass gjs_union_class = {
     NULL,  /* setProperty */
     NULL,  /* enumerate */
     union_resolve,
-    nullptr,  /* mayResolve */
+    union_may_resolve,
     union_finalize
 };
 
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index 505f717..9030390 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -796,10 +796,10 @@ importer_resolve(JSContext        *context,
 {
     Importer *priv;
     char *name = NULL;
-    jsid module_init_name;
 
-    module_init_name = gjs_context_get_const_string(context, GJS_STRING_MODULE_INIT);
-    if (id == module_init_name) {
+    if (id == gjs_context_get_const_string(context, GJS_STRING_MODULE_INIT) ||
+        id == gjs_context_get_const_string(context, GJS_STRING_CONSTRUCTOR) ||
+        id == gjs_context_get_const_string(context, GJS_STRING_PROTOTYPE)) {
         *resolved = false;
         return true;
     }
diff --git a/gjs/jsapi-class.h b/gjs/jsapi-class.h
index 47696e0..954a8c0 100644
--- a/gjs/jsapi-class.h
+++ b/gjs/jsapi-class.h
@@ -54,6 +54,10 @@ JSObject *gjs_construct_object_dynamic(JSContext                  *cx,
                                        JS::HandleObject            proto,
                                        const JS::HandleValueArray& args);
 
+bool gjs_dynamic_class_default_may_resolve(const JSAtomState& names,
+                                           jsid               id,
+                                           JSObject          *maybe_obj);
+
 /*
  * Helper methods to access private data:
  *
diff --git a/gjs/jsapi-dynamic-class.cpp b/gjs/jsapi-dynamic-class.cpp
index d0e947b..3f01c4e 100644
--- a/gjs/jsapi-dynamic-class.cpp
+++ b/gjs/jsapi-dynamic-class.cpp
@@ -61,6 +61,9 @@ gjs_init_class_dynamic(JSContext              *context,
     /* Without a name, JS_NewObject fails */
     g_assert (clasp->name != NULL);
 
+    g_assert(((void) "If you have a resolve hook, you also need mayResolve",
+              (clasp->resolve == nullptr) == (clasp->mayResolve == nullptr)));
+
     /* gjs_init_class_dynamic only makes sense for instantiable classes,
        use JS_InitClass for static classes like Math */
     g_assert (constructor_native != NULL);
@@ -194,3 +197,30 @@ gjs_construct_object_dynamic(JSContext                  *context,
 
     return JS_New(context, constructor, args);
 }
+
+/**
+ * gjs_dynamic_class_default_may_resolve:
+ * @names: SpiderMonkey internal, unused
+ * @id: property ID being queried
+ * @maybe_obj: object being queried, or nullptr if not known
+ *
+ * If you have a resolve hook on a dynamic class, you also need a mayResolve
+ * hook. Otherwise, when gjs_init_class_dynamic() calls
+ * JS_LinkConstructorAndPrototype(), the resolve hook will be called to resolve
+ * the "constructor" and "prototype" properties first.
+ *
+ * If you don't have any other predefined properties or methods that you want
+ * to prevent from being resolved, you can just use this function as the
+ * mayResolve hook.
+ */
+bool
+gjs_dynamic_class_default_may_resolve(const JSAtomState& names,
+                                      jsid               id,
+                                      JSObject          *maybe_obj)
+{
+    if (!JSID_IS_STRING(id))
+        return false;
+    JSFlatString *str = JSID_TO_FLAT_STRING(id);
+    return !(JS_FlatStringEqualsAscii(str, "constructor") ||
+             JS_FlatStringEqualsAscii(str, "prototype"));
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]