[gjs/april-maintenance: 9/11] function: Use JS::CallArgs throughout invocation call chain



commit 4c4dfd416cae36d85d69d58ae358595589219fa3
Author: Philip Chimento <philip chimento gmail com>
Date:   Thu Apr 30 21:15:22 2020 -0700

    function: Use JS::CallArgs throughout invocation call chain
    
    If you have a JSObject for the 'this' object, a JS::Value array for the
    arguments, and a mutable JS::Value for the return value, then that's
    basically a JS::CallArgs.
    
    The only difference is that when calling a constructor, you may not be
    able to get the 'this' object from args.computeThis(). For
    gjs_invoke_constructor_from_c(), we need to provide the 'this' object
    that was provided to the constructor.

 gi/function.cpp    | 70 ++++++++++++++++++++++--------------------------------
 gi/function.h      |  3 ++-
 gi/fundamental.cpp |  2 +-
 gi/fundamental.h   |  3 +--
 gi/union.cpp       | 14 ++++-------
 5 files changed, 38 insertions(+), 54 deletions(-)
---
diff --git a/gi/function.cpp b/gi/function.cpp
index e65d09ff..45b05ca4 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -784,21 +784,17 @@ complete_async_calls(void)
     }
 }
 
-/*
- * This function can be called in 2 different ways. You can either use
- * it to create javascript objects by providing a @js_rval argument or
- * you can decide to keep the return values in #GArgument format by
- * providing a @r_value argument.
- */
+// This function can be called in two different ways. You can either use it to
+// create JavaScript objects by calling it without @r_value, or you can decide
+// to keep the return values in #GArgument format by providing a @r_value
+// argument.
 GJS_JSAPI_RETURN_CONVENTION
-static bool gjs_invoke_c_function(
-    JSContext* context, Function* function,
-    JS::HandleObject obj, /* "this" object */
-    const JS::HandleValueArray& args,
-    mozilla::Maybe<JS::MutableHandleValue> js_rval,
-    GIArgument* r_value = nullptr) {
-    g_assert(!r_value != js_rval.isNothing() &&
-             "Pass one of js_rval or r_value, not both or neither");
+static bool gjs_invoke_c_function(JSContext* context, Function* function,
+                                  const JS::CallArgs& args,
+                                  JS::HandleObject this_obj = nullptr,
+                                  GIArgument* r_value = nullptr) {
+    g_assert((args.isConstructing() || !this_obj) &&
+             "If not a constructor, then pass the 'this' object via CallArgs");
 
     /* These first four are arrays which hold argument pointers.
      * @in_arg_cvalues: C values which are passed on input (in or inout)
@@ -856,19 +852,14 @@ static bool gjs_invoke_c_function(
      *
      * @args.length() is the number of arguments that were actually passed.
      */
+    GjsAutoChar name = format_function_name(function, is_method);
     if (args.length() > function->expected_js_argc) {
-        GjsAutoChar name = format_function_name(function, is_method);
-        if (!JS::WarnUTF8(context,
-                          "Too many arguments to %s: expected %d, "
-                          "got %" G_GSIZE_FORMAT,
-                          name.get(), function->expected_js_argc,
-                          args.length()))
+        if (!JS::WarnUTF8(
+                context, "Too many arguments to %s: expected %d, got %u",
+                name.get(), function->expected_js_argc, args.length()))
             return false;
-    } else if (args.length() < function->expected_js_argc) {
-        GjsAutoChar name = format_function_name(function, is_method);
-        gjs_throw(context, "Too few arguments to %s: "
-                  "expected %d, got %" G_GSIZE_FORMAT,
-                  name.get(), function->expected_js_argc, args.length());
+    } else if (!args.requireAtLeast(context, name,
+                                    function->expected_js_argc)) {
         return false;
     }
 
@@ -884,6 +875,10 @@ static bool gjs_invoke_c_function(
     c_arg_pos = 0; /* index into in_arg_cvalues, etc */
     js_arg_pos = 0; /* index into argv */
 
+    JS::RootedObject obj(context, this_obj);
+    if (!args.isConstructing() && !args.computeThis(context, &obj))
+        return false;
+
     if (is_method) {
         if (!gjs_fill_method_instance(context, obj, function,
                                       &in_arg_cvalues[0], is_object_method))
@@ -990,7 +985,8 @@ static bool gjs_invoke_c_function(
                     callable_info = (GICallableInfo*) g_type_info_get_interface(&ainfo);
                     trampoline = gjs_callback_trampoline_new(
                         context, func, callable_info, scope,
-                        is_object_method ? obj : nullptr, false);
+                        is_object_method ? JS::HandleObject(obj) : nullptr,
+                        false);
                     closure = trampoline->closure;
                     g_base_info_unref(callable_info);
                 }
@@ -1144,7 +1140,7 @@ static bool gjs_invoke_c_function(
     }
 
     if (!r_value)
-        js_rval->setUndefined();
+        args.rval().setUndefined();
 
     /* Only process return values if the function didn't throw */
     if (function->js_out_argc > 0 && !did_throw_gerror) {
@@ -1412,14 +1408,14 @@ release:
             // own, otherwise return a JavaScript array with [return value,
             // out arg 1, out arg 2, ...]
             if (function->js_out_argc == 1) {
-                js_rval->set(return_values[0]);
+                args.rval().set(return_values[0]);
             } else {
                 JSObject *array;
                 array = JS_NewArrayObject(context, return_values);
                 if (array == NULL) {
                     failed = true;
                 } else {
-                    js_rval->setObject(*array);
+                    args.rval().setObject(*array);
                 }
             }
         }
@@ -1440,12 +1436,10 @@ function_call(JSContext *context,
               unsigned   js_argc,
               JS::Value *vp)
 {
-    GJS_GET_THIS(context, js_argc, vp, js_argv, object);
+    JS::CallArgs js_argv = JS::CallArgsFromVp(js_argc, vp);
     JS::RootedObject callee(context, &js_argv.callee());
 
-    bool success;
     Function *priv;
-    JS::RootedValue retval(context);
 
     priv = priv_from_js(context, callee);
     gjs_debug_marshal(GJS_DEBUG_GFUNCTION,
@@ -1455,12 +1449,7 @@ function_call(JSContext *context,
     if (priv == NULL)
         return true; /* we are the prototype, or have the wrong class */
 
-    success = gjs_invoke_c_function(context, priv, object, js_argv,
-                                    mozilla::Some(&retval));
-    if (success)
-        js_argv.rval().set(retval);
-
-    return success;
+    return gjs_invoke_c_function(context, priv, js_argv);
 }
 
 GJS_NATIVE_CONSTRUCTOR_DEFINE_ABSTRACT(function)
@@ -1858,7 +1847,7 @@ gjs_define_function(JSContext       *context,
 
 bool gjs_invoke_constructor_from_c(JSContext* context, GIFunctionInfo* info,
                                    JS::HandleObject obj,
-                                   const JS::HandleValueArray& args,
+                                   const JS::CallArgs& args,
                                    GIArgument* rvalue) {
     Function function;
 
@@ -1866,8 +1855,7 @@ bool gjs_invoke_constructor_from_c(JSContext* context, GIFunctionInfo* info,
     if (!init_cached_function_data(context, &function, 0, info))
         return false;
 
-    bool result = gjs_invoke_c_function(context, &function, obj, args,
-                                        mozilla::Nothing(), rvalue);
+    bool result = gjs_invoke_c_function(context, &function, args, obj, rvalue);
     uninit_cached_function_data(&function);
     return result;
 }
diff --git a/gi/function.h b/gi/function.h
index eef77afd..f8e251fc 100644
--- a/gi/function.h
+++ b/gi/function.h
@@ -30,6 +30,7 @@
 #include <girepository.h>
 #include <glib-object.h>
 
+#include <js/CallArgs.h>
 #include <js/TypeDecls.h>
 
 #include "gjs/macros.h"
@@ -76,7 +77,7 @@ JSObject *gjs_define_function(JSContext       *context,
 GJS_JSAPI_RETURN_CONVENTION
 bool gjs_invoke_constructor_from_c(JSContext* cx, GIFunctionInfo* info,
                                    JS::HandleObject this_obj,
-                                   const JS::HandleValueArray& args,
+                                   const JS::CallArgs& args,
                                    GIArgument* rvalue);
 
 #endif  // GI_FUNCTION_H_
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index bde80edd..2d3ef787 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -187,7 +187,7 @@ bool FundamentalPrototype::resolve_impl(JSContext* cx, JS::HandleObject obj,
  */
 bool FundamentalInstance::invoke_constructor(JSContext* context,
                                              JS::HandleObject obj,
-                                             const JS::HandleValueArray& args,
+                                             const JS::CallArgs& args,
                                              GIArgument* rvalue) {
     GIFunctionInfo* constructor_info = get_prototype()->constructor_info();
     if (!constructor_info) {
diff --git a/gi/fundamental.h b/gi/fundamental.h
index a1a9f363..465b93a8 100644
--- a/gi/fundamental.h
+++ b/gi/fundamental.h
@@ -158,8 +158,7 @@ class FundamentalInstance
 
     GJS_JSAPI_RETURN_CONVENTION
     bool invoke_constructor(JSContext* cx, JS::HandleObject obj,
-                            const JS::HandleValueArray& args,
-                            GIArgument* rvalue);
+                            const JS::CallArgs& args, GIArgument* rvalue);
 
     void ref(void) { get_prototype()->call_ref_function(m_ptr); }
     void unref(void) { get_prototype()->call_unref_function(m_ptr); }
diff --git a/gi/union.cpp b/gi/union.cpp
index 34720f38..9661562f 100644
--- a/gi/union.cpp
+++ b/gi/union.cpp
@@ -95,11 +95,8 @@ bool UnionPrototype::resolve_impl(JSContext* context, JS::HandleObject obj,
 }
 
 GJS_JSAPI_RETURN_CONVENTION
-static void*
-union_new(JSContext       *context,
-          JS::HandleObject obj, /* "this" for constructor */
-          GIUnionInfo     *info)
-{
+static void* union_new(JSContext* context, JS::HandleObject this_obj,
+                       const JS::CallArgs& args, GIUnionInfo* info) {
     int n_methods;
     int i;
 
@@ -116,9 +113,8 @@ union_new(JSContext       *context,
         if ((flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0 &&
             g_callable_info_get_n_args((GICallableInfo*) func_info) == 0) {
             GIArgument rval;
-            if (!gjs_invoke_constructor_from_c(context, func_info, obj,
-                                               JS::HandleValueArray::empty(),
-                                               &rval))
+            if (!gjs_invoke_constructor_from_c(context, func_info, this_obj,
+                                               args, &rval))
                 return nullptr;
 
             if (!rval.v_pointer) {
@@ -148,7 +144,7 @@ bool UnionInstance::constructor_impl(JSContext* context,
                       name()))
         return false;
 
-    m_ptr = union_new(context, object, info());
+    m_ptr = union_new(context, object, args, info());
     return !!m_ptr;
 }
 


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