コード例 #1
0
ファイル: closure.cpp プロジェクト: smspillaz/gjs
void
gjs_closure_invoke(GClosure *closure,
                   int       argc,
                   jsval    *argv,
                   jsval    *retval)
{
    Closure *c;
    JSContext *context;
    JSObject *global;

    c = (Closure*) closure;

    check_context_valid(c);

    if (c->obj == NULL) {
        /* We were destroyed; become a no-op */
        c->context = NULL;
        return;
    }

    context = gjs_runtime_get_context(c->runtime);
    JS_BeginRequest(context);
    global = JS_GetGlobalObject(context);
    JSAutoCompartment ac(context, global);

    if (JS_IsExceptionPending(context)) {
        gjs_debug_closure("Exception was pending before invoking callback??? "
                          "Not expected");
        gjs_log_exception(context);
    }

    if (!gjs_call_function_value(context,
                                 NULL, /* "this" object; NULL is some kind of default presumably */
                                 OBJECT_TO_JSVAL(c->obj),
                                 argc,
                                 argv,
                                 retval)) {
        /* Exception thrown... */
        gjs_debug_closure("Closure invocation failed (exception should "
                          "have been thrown) closure %p callable %p",
                          closure, c->obj);
        if (!gjs_log_exception(context))
            gjs_debug_closure("Closure invocation failed but no exception was set?");
        goto out;
    }

    if (gjs_log_exception(context)) {
        gjs_debug_closure("Closure invocation succeeded but an exception was set");
    }

 out:
    JS_EndRequest(context);
}
コード例 #2
0
ファイル: context.c プロジェクト: RavetcoFX/cjs
gboolean
gjs_context_define_string_array(GjsContext  *js_context,
                                const char    *array_name,
                                gssize         array_length,
                                const char   **array_values,
                                GError       **error)
{
    if (!gjs_define_string_array(js_context->context,
                                 js_context->global,
                                 array_name, array_length, array_values,
                                 JSPROP_READONLY | JSPROP_PERMANENT)) {
        char *message;

        message = NULL;
        gjs_log_exception(js_context->context, &message);
        if (message) {
            g_set_error(error,
                        GJS_ERROR,
                        GJS_ERROR_FAILED,
                        "%s", message);
            g_free(message);
        } else {
            message = "gjs_define_string_array() failed but no exception message?";
            gjs_debug(GJS_DEBUG_CONTEXT, "%s", message);
            g_set_error(error,
                        GJS_ERROR,
                        GJS_ERROR_FAILED,
                        "%s", message);
        }
        return FALSE;
    }

    return TRUE;
}
コード例 #3
0
ファイル: gerror.cpp プロジェクト: 3dfxmadscientist/cjs
void
gjs_define_error_class(JSContext    *context,
                       JSObject     *in_object,
                       GIEnumInfo   *info)
{
    const char *constructor_name;
    GIBoxedInfo *glib_error_info;
    JSObject *prototype, *parent_proto;
    JSObject *constructor;
    Error *priv;

    /* See the comment in gjs_define_boxed_class() for an
     * explanation of how this all works; Error is pretty much the
     * same as Boxed (except that we inherit from GLib.Error).
     */

    constructor_name = g_base_info_get_name( (GIBaseInfo*) info);

    g_irepository_require(NULL, "GLib", "2.0", (GIRepositoryLoadFlags) 0, NULL);
    glib_error_info = (GIBoxedInfo*) g_irepository_find_by_name(NULL, "GLib", "Error");
    parent_proto = gjs_lookup_generic_prototype(context, glib_error_info);
    g_base_info_unref((GIBaseInfo*)glib_error_info);

    if (!gjs_init_class_dynamic(context, in_object,
                                parent_proto,
                                g_base_info_get_namespace( (GIBaseInfo*) info),
                                constructor_name,
                                &gjs_error_class,
                                gjs_error_constructor, 1,
                                /* props of prototype */
                                &gjs_error_proto_props[0],
                                /* funcs of prototype */
                                &gjs_error_proto_funcs[0],
                                /* props of constructor, MyConstructor.myprop */
                                NULL,
                                /* funcs of constructor, MyConstructor.myfunc() */
                                &gjs_error_constructor_funcs[0],
                                &prototype,
                                &constructor)) {
        gjs_log_exception(context);
        g_error("Can't init class %s", constructor_name);
    }

    GJS_INC_COUNTER(gerror);
    priv = g_slice_new0(Error);
    priv->info = info;
    g_base_info_ref( (GIBaseInfo*) priv->info);
    priv->domain = g_quark_from_string (g_enum_info_get_error_domain(priv->info));

    JS_SetPrivate(prototype, priv);

    gjs_debug(GJS_DEBUG_GBOXED, "Defined class %s prototype is %p class %p in object %p",
              constructor_name, prototype, JS_GetClass(prototype), in_object);

    gjs_define_enum_values(context, constructor, priv->info);
    gjs_define_enum_static_methods(context, constructor, priv->info);
}
コード例 #4
0
ファイル: coverage.cpp プロジェクト: leigh123linux/cjs
static void
gjs_coverage_constructed(GObject *object)
{
    G_OBJECT_CLASS(gjs_coverage_parent_class)->constructed(object);

    GjsCoverage *coverage = GJS_COVERAGE(object);
    GjsCoveragePrivate *priv = (GjsCoveragePrivate *) gjs_coverage_get_instance_private(coverage);
    new (&priv->compartment) JS::Heap<JSObject *>();

    if (!bootstrap_coverage(coverage)) {
        JSContext *context = static_cast<JSContext *>(gjs_context_get_native_context(priv->context));
        JSAutoCompartment compartment(context, gjs_get_import_global(context));
        gjs_log_exception(context);
    }
}
コード例 #5
0
ファイル: shell-global.c プロジェクト: MarkieMark/gnome-shell
/**
 * shell_global_add_extension_importer:
 * @target_object_script: JavaScript code evaluating to a target object
 * @target_property: Name of property to use for importer
 * @directory: Source directory:
 * @error: A #GError
 *
 * This function sets a property named @target_property on the object
 * resulting from the evaluation of @target_object_script code, which
 * acts as a GJS importer for directory @directory.
 *
 * Returns: %TRUE on success
 */
gboolean
shell_global_add_extension_importer (ShellGlobal *global,
                                     const char  *target_object_script,
                                     const char  *target_property,
                                     const char  *directory,
                                     GError     **error)
{
  jsval target_object;
  JSObject *importer;
  JSContext *context = gjs_context_get_native_context (global->js_context);
  char *search_path[2] = { 0, 0 };

  // This is a bit of a hack; ideally we'd be able to pass our target
  // object directly into this function, but introspection doesn't
  // support that at the moment.  Instead evaluate a string to get it.
  if (!JS_EvaluateScript(context,
                         JS_GetGlobalObject(context),
                         target_object_script,
                         strlen (target_object_script),
                         "<target_object_script>",
                         0,
                         &target_object))
    {
      char *message;
      gjs_log_exception(context,
                        &message);
      g_set_error(error,
                  G_IO_ERROR,
                  G_IO_ERROR_FAILED,
                  "%s", message ? message : "(unknown)");
      g_free(message);
      return FALSE;
    }

  if (!JSVAL_IS_OBJECT (target_object))
    {
      g_error ("shell_global_add_extension_importer: invalid target object");
      return FALSE;
    }

  search_path[0] = (char*)directory;
  importer = gjs_define_importer (context, JSVAL_TO_OBJECT (target_object), target_property, (const char **)search_path, FALSE);
  return TRUE;
}
コード例 #6
0
ファイル: jsapi-util.c プロジェクト: sjokkis/gjs
const char*
gjs_value_debug_string(JSContext      *context,
                       jsval           value)
{
    JSString *str;
    const char *bytes;

    JS_BeginRequest(context);

    str = JS_ValueToString(context, value);

    if (str == NULL) {
        if (JSVAL_IS_OBJECT(value)) {
            /* Specifically the Call object (see jsfun.c in spidermonkey)
             * does not have a toString; there may be others also.
             */
            JSClass *klass;

            klass = JS_GET_CLASS(context, JSVAL_TO_OBJECT(value));
            if (klass != NULL) {
                str = JS_NewStringCopyZ(context, klass->name);
                JS_ClearPendingException(context);
                if (str == NULL) {
                    return "[out of memory copying class name]";
                }
            } else {
                gjs_log_exception(context, NULL);
                return "[unknown object]";
            }
        } else {
            return "[unknown non-object]";
        }
    }

    g_assert(str != NULL);

    bytes = JS_GetStringBytes(str);

    JS_EndRequest(context);

    return bytes;
}
コード例 #7
0
ファイル: peas-extension-gjs.c プロジェクト: OBERTANK/libpeas
static gboolean
peas_extension_gjs_call (PeasExtensionWrapper *exten,
                         GType                 exten_type,
                         GICallableInfo       *func_info,
                         const gchar          *method_name,
                         GIArgument           *args,
                         GIArgument           *retval)
{
  PeasExtensionGjs *gexten = PEAS_EXTENSION_GJS (exten);
  gboolean success = FALSE;
  jsval js_method, js_retval;
  jsval *js_args;
  CachedArg *arg_cache;
  gint i, n_args, nth_out_arg;
  gint n_in_args = 0;
  gint n_out_args = 0;
  gint cached_args = 0;

  /* Fetch the JS method we want to call */
  if (!JS_GetProperty (gexten->js_context, gexten->js_object,
                       method_name, &js_method) ||
      JSVAL_IS_VOID (js_method))
    {
      g_warning ("Method '%s.%s' was not found",
                 g_type_name (exten_type), method_name);
      return FALSE;
    }

  if (JSVAL_IS_NULL (js_method) || !JSVAL_IS_OBJECT (js_method) ||
      !JS_ObjectIsFunction (gexten->js_context, JSVAL_TO_OBJECT (js_method)))
    {
      g_warning ("Method '%s.%s' in not a function",
                 g_type_name (exten_type), method_name);
      return FALSE;
    }

  n_args = g_callable_info_get_n_args (func_info);
  if (n_args < 0)
    {
      g_warn_if_fail (n_args >= 0);
      return FALSE;
    }

  js_args = g_newa (jsval, n_args);
  arg_cache = g_newa (CachedArg, n_args + 1);

  /* Return value is an out arg */
  g_callable_info_load_return_type (func_info, &arg_cache[0].type_info);
  if (g_type_info_get_tag (&arg_cache[0].type_info) != GI_TYPE_TAG_VOID)
    {
      ++n_out_args;
      arg_cache[cached_args++].ptr = &retval->v_pointer;
    }

  /* Handle the arguments */
  for (i = 0; i < n_args; ++i, ++cached_args)
    {
      GIDirection direction;

      g_callable_info_load_arg (func_info, i, &arg_cache[cached_args].arg_info);
      direction = g_arg_info_get_direction (&arg_cache[cached_args].arg_info);
      g_arg_info_load_type (&arg_cache[cached_args].arg_info,
                            &arg_cache[cached_args].type_info);

      if (direction == GI_DIRECTION_IN &&
          !gjs_value_from_g_argument (gexten->js_context, &js_args[n_in_args++],
                                      &arg_cache[cached_args].type_info,
                                      &args[i], TRUE))
        {
          g_warning ("Error failed to convert argument '%s'",
                     g_base_info_get_name (&arg_cache[cached_args].arg_info));
          return FALSE;
        }

      if (direction == GI_DIRECTION_INOUT)
        {
          GIArgument arg;

          peas_gi_pointer_to_argument (&arg_cache[cached_args].type_info,
                                       args[i].v_pointer, &arg);

          if (!gjs_value_from_g_argument (gexten->js_context, &js_args[n_in_args++],
                                          &arg_cache[cached_args].type_info, &arg, TRUE))
            {
              g_warning ("Error failed to convert argument '%s'",
                         g_base_info_get_name (&arg_cache[cached_args].arg_info));
              return FALSE;
            }
        }

      if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
        {
          ++n_out_args;
          arg_cache[cached_args].ptr = args[i].v_pointer;
        }
    }

  success = JS_CallFunctionValue (gexten->js_context, gexten->js_object,
                                  js_method, n_in_args, js_args, &js_retval);

  if (!success)
    {
      if (!gjs_log_exception (gexten->js_context, NULL))
        {
          g_warning ("Error while calling '%s.%s'",
                     g_type_name (exten_type), method_name);
        }

      return FALSE;
    }

  /* First we need to release in argument */
  for (i = 0; i < cached_args; ++i)
    {
      GIDirection direction;

      /* First cached argument may be the return value */
      if (i == 0 && cached_args > n_args)
        continue;

      direction = g_arg_info_get_direction (&arg_cache[i].arg_info);

      if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
        {
          GITransfer transfer;

          transfer = g_arg_info_get_ownership_transfer (&arg_cache[i].arg_info);

          if (!gjs_g_argument_release_in_arg (gexten->js_context, transfer,
                                              &arg_cache[i].type_info,
                                              &args[i]))
            {
              g_warning ("Error failed to release IN argument '%s'",
                         g_base_info_get_name (&arg_cache[i].arg_info));
            }
        }
    }

  /* Check that we have a valid return value */
  if (n_out_args > 1)
    {
      if (!JSVAL_IS_OBJECT (js_retval) ||
          !JS_IsArrayObject (gexten->js_context, JSVAL_TO_OBJECT (js_retval)))
        {
          g_warning ("Error return value is not an array");
          return FALSE;
        }
    }

  /* Set out arguments */
  for (i = 0, nth_out_arg = 0; i < cached_args && success; ++i)
    {
      gboolean is_return_value;

      is_return_value = i == 0 && cached_args > n_args;

      /* Return value does not have a GIArgInfo and is always out */
      if (!is_return_value)
        {
          GIDirection direction;

          direction = g_arg_info_get_direction (&arg_cache[i].arg_info);

          if (direction == GI_DIRECTION_IN)
            continue;
        }

      if (n_out_args == 1)
        {
          success = set_out_arg (gexten->js_context, func_info, is_return_value,
                                 &arg_cache[i].arg_info, &arg_cache[i].type_info,
                                 arg_cache[i].ptr, js_retval);
          break;
        }
      else if (n_out_args > 1)
        {
          jsval js_value;

          if (!JS_GetElement (gexten->js_context, JSVAL_TO_OBJECT (js_retval),
                              nth_out_arg++, &js_value) ||
              js_value == JSVAL_VOID)
            {
              g_warning ("Error failed to get out argument %i", nth_out_arg);
              return FALSE;
            }
          else
            {
              success = set_out_arg (gexten->js_context, func_info,
                                     is_return_value, &arg_cache[i].arg_info,
                                     &arg_cache[i].type_info, arg_cache[i].ptr,
                                     js_value);
            }
        }
    }

  return success;
}
コード例 #8
0
ファイル: keep-alive.c プロジェクト: KNOPOChKA2/gjs
JSObject*
gjs_keep_alive_new(JSContext *context)
{
    JSObject *keep_alive;
    JSObject *global;

    /* This function creates an unattached KeepAlive object; following our
     * general strategy, we have a single KeepAlive class with a constructor
     * stored on our single "load global" pseudo-global object, and we create
     * instances with the load global as parent.
     */

    g_assert(context != NULL);

    JS_BeginRequest(context);

    global = gjs_get_import_global(context);

    g_assert(global != NULL);

    if (!gjs_object_has_property(context, global, gjs_keep_alive_class.name)) {
        JSObject *prototype;

        gjs_debug(GJS_DEBUG_KEEP_ALIVE,
                  "Initializing keep-alive class in context %p global %p",
                  context, global);

        prototype = JS_InitClass(context, global,
                                 /* parent prototype JSObject* for
                                  * prototype; NULL for
                                  * Object.prototype
                                  */
                                 NULL,
                                 &gjs_keep_alive_class,
                                 /* constructor for instances (NULL for
                                  * none - just name the prototype like
                                  * Math - rarely correct)
                                  */
                                 gjs_keep_alive_constructor,
                                 /* number of constructor args */
                                 0,
                                 /* props of prototype */
                                 &gjs_keep_alive_proto_props[0],
                                 /* funcs of prototype */
                                 &gjs_keep_alive_proto_funcs[0],
                                 /* props of constructor, MyConstructor.myprop */
                                 NULL,
                                 /* funcs of constructor, MyConstructor.myfunc() */
                                 NULL);
        if (prototype == NULL)
            gjs_fatal("Can't init class %s", gjs_keep_alive_class.name);

        g_assert(gjs_object_has_property(context, global, gjs_keep_alive_class.name));

        gjs_debug(GJS_DEBUG_KEEP_ALIVE, "Initialized class %s prototype %p",
                  gjs_keep_alive_class.name, prototype);
    }

    gjs_debug(GJS_DEBUG_KEEP_ALIVE,
              "Creating new keep-alive object for context %p global %p",
              context, global);

    keep_alive = JS_ConstructObject(context, &gjs_keep_alive_class, NULL, global);
    if (keep_alive == NULL) {
        gjs_log_exception(context, NULL);
        gjs_fatal("Failed to create keep_alive object");
    }

    JS_EndRequest(context);

    return keep_alive;
}
コード例 #9
0
ファイル: fundamental.cpp プロジェクト: victoryang/gjs
JSBool
gjs_define_fundamental_class(JSContext     *context,
                             JSObject      *in_object,
                             GIObjectInfo  *info,
                             JSObject     **constructor_p,
                             JSObject     **prototype_p)
{
    const char *constructor_name;
    JSObject *prototype;
    jsval value;
    jsid js_constructor_name = JSID_VOID;
    JSObject *parent_proto;
    Fundamental *priv;
    JSObject *constructor;
    GType parent_gtype;
    GType gtype;
    GIFunctionInfo *constructor_info;
    /* See the comment in gjs_define_object_class() for an explanation
     * of how this all works; Fundamental is pretty much the same as
     * Object.
     */

    constructor_name = g_base_info_get_name((GIBaseInfo *) info);
    constructor_info = find_fundamental_constructor(context, info,
                                                    &js_constructor_name);

    gtype = g_registered_type_info_get_g_type (info);
    parent_gtype = g_type_parent(gtype);
    parent_proto = NULL;
    if (parent_gtype != G_TYPE_INVALID)
        parent_proto = gjs_lookup_fundamental_prototype_from_gtype(context,
                                                                   parent_gtype);

    if (!gjs_init_class_dynamic(context, in_object,
                                /* parent prototype JSObject* for
                                 * prototype; NULL for
                                 * Object.prototype
                                 */
                                parent_proto,
                                g_base_info_get_namespace((GIBaseInfo *) info),
                                constructor_name,
                                &gjs_fundamental_instance_class,
                                gjs_fundamental_instance_constructor,
                                /* number of constructor args (less can be passed) */
                                constructor_info != NULL ? g_callable_info_get_n_args((GICallableInfo *) constructor_info) : 0,
                                /* props of prototype */
                                parent_proto ? NULL : &gjs_fundamental_instance_proto_props[0],
                                /* funcs of prototype */
                                parent_proto ? NULL : &gjs_fundamental_instance_proto_funcs[0],
                                /* props of constructor, MyConstructor.myprop */
                                NULL,
                                /* funcs of constructor, MyConstructor.myfunc() */
                                NULL,
                                &prototype,
                                &constructor)) {
        gjs_log_exception(context);
        g_error("Can't init class %s", constructor_name);
    }

    /* Put the info in the prototype */
    priv = g_slice_new0(Fundamental);
    g_assert(priv != NULL);
    g_assert(priv->info == NULL);
    priv->info = g_base_info_ref((GIBaseInfo *) info);
    priv->gtype = gtype;
    priv->constructor_name = js_constructor_name;
    priv->constructor_info = constructor_info;
    priv->ref_function = g_object_info_get_ref_function_pointer(info);
    g_assert(priv->ref_function != NULL);
    priv->unref_function = g_object_info_get_unref_function_pointer(info);
    g_assert(priv->unref_function != NULL);
    priv->set_value_function = g_object_info_get_set_value_function_pointer(info);
    g_assert(priv->set_value_function != NULL);
    priv->get_value_function = g_object_info_get_get_value_function_pointer(info);
    g_assert(priv->get_value_function != NULL);
    JS_SetPrivate(prototype, priv);

    gjs_debug(GJS_DEBUG_GFUNDAMENTAL,
              "Defined class %s prototype is %p class %p in object %p constructor %s.%s.%s",
              constructor_name, prototype, JS_GetClass(prototype),
              in_object,
              constructor_info != NULL ? g_base_info_get_namespace(constructor_info) : "unknown",
              constructor_info != NULL ? g_base_info_get_name(g_base_info_get_container(constructor_info)) : "unknown",
              constructor_info != NULL ? g_base_info_get_name(constructor_info) : "unknown");

    if (g_object_info_get_n_fields(priv->info) > 0) {
        gjs_debug(GJS_DEBUG_GFUNDAMENTAL,
                  "Fundamental type '%s.%s' apparently has accessible fields. "
                  "Gjs has no support for this yet, ignoring these.",
                  g_base_info_get_namespace((GIBaseInfo *)priv->info),
                  g_base_info_get_name ((GIBaseInfo *)priv->info));
    }

    gjs_object_define_static_methods(context, constructor, gtype, info);

    value = OBJECT_TO_JSVAL(gjs_gtype_create_gtype_wrapper(context, gtype));
    JS_DefineProperty(context, constructor, "$gtype", value,
                      NULL, NULL, JSPROP_PERMANENT);

    if (constructor_p)
        *constructor_p = constructor;
    if (prototype_p)
        *prototype_p = prototype;

    return JS_TRUE;
}
コード例 #10
0
ファイル: keep-alive.cpp プロジェクト: GNOME/gjs
static JSObject *
gjs_keep_alive_new(JSContext *context)
{
    KeepAlive *priv;
    bool found;

    /* This function creates an unattached KeepAlive object; following our
     * general strategy, we have a single KeepAlive class with a constructor
     * stored on our single "load global" pseudo-global object, and we create
     * instances with the load global as parent.
     */

    g_assert(context != NULL);

    JSAutoRequest ar(context);

    JS::RootedObject global(context, gjs_get_import_global(context));

    g_assert(global != NULL);

    if (!JS_HasProperty(context, global, gjs_keep_alive_class.name, &found))
        return NULL;

    if (!found) {
        JSObject *prototype;

        gjs_debug(GJS_DEBUG_KEEP_ALIVE,
                  "Initializing keep-alive class in context %p global %p",
                  context, global.get());

        prototype = JS_InitClass(context, global,
                                 /* parent prototype JSObject* for
                                  * prototype; NULL for
                                  * Object.prototype
                                  */
                                 JS::NullPtr(),
                                 &gjs_keep_alive_class,
                                 /* constructor for instances (NULL for
                                  * none - just name the prototype like
                                  * Math - rarely correct)
                                  */
                                 gjs_keep_alive_constructor,
                                 /* number of constructor args */
                                 0,
                                 /* props of prototype */
                                 &gjs_keep_alive_proto_props[0],
                                 /* funcs of prototype */
                                 &gjs_keep_alive_proto_funcs[0],
                                 /* props of constructor, MyConstructor.myprop */
                                 NULL,
                                 /* funcs of constructor, MyConstructor.myfunc() */
                                 NULL);
        if (prototype == NULL)
            g_error("Can't init class %s", gjs_keep_alive_class.name);

        gjs_debug(GJS_DEBUG_KEEP_ALIVE, "Initialized class %s prototype %p",
                  gjs_keep_alive_class.name, prototype);
    }

    gjs_debug(GJS_DEBUG_KEEP_ALIVE,
              "Creating new keep-alive object for context %p global %p",
              context, global.get());

    JS::RootedObject keep_alive(context,
        JS_NewObject(context, &gjs_keep_alive_class, JS::NullPtr(), global));
    if (keep_alive == NULL) {
        gjs_log_exception(context);
        g_error("Failed to create keep_alive object");
    }

    priv = g_slice_new0(KeepAlive);
    priv->children = g_hash_table_new_full(child_hash, child_equal, NULL, child_free);

    g_assert(priv_from_js(context, keep_alive) == NULL);
    JS_SetPrivate(keep_alive, priv);

    gjs_debug_lifecycle(GJS_DEBUG_KEEP_ALIVE,
                        "keep_alive constructor, obj %p priv %p",
                        keep_alive.get(), priv);

    return keep_alive;
}
コード例 #11
0
ファイル: gerror.c プロジェクト: Cobinja/cjs
JSBool
gjs_define_error_class(JSContext    *context,
                       JSObject     *in_object,
                       GIEnumInfo   *info,
                       JSObject    **constructor_p,
                       JSObject    **prototype_p)
{
    const char *constructor_name;
    GIBoxedInfo *glib_error_info;
    JSObject *prototype, *parent_proto;
    JSObject *constructor;
    jsval value;
    Error *priv;

    /* See the comment in gjs_define_boxed_class() for an
     * explanation of how this all works; Error is pretty much the
     * same as Boxed (except that we inherit from GLib.Error).
     */

    constructor_name = g_base_info_get_name( (GIBaseInfo*) info);

    if (gjs_object_get_property(context, in_object, constructor_name, &value)) {
        JSObject *constructor;

        if (!JSVAL_IS_OBJECT(value)) {
            gjs_throw(context, "Existing property '%s' does not look like a constructor",
                         constructor_name);
            return JS_FALSE;
        }

        constructor = JSVAL_TO_OBJECT(value);

        gjs_object_get_property(context, constructor, "prototype", &value);
        if (!JSVAL_IS_OBJECT(value)) {
            gjs_throw(context, "error %s prototype property does not appear to exist or has wrong type", constructor_name);
            return JS_FALSE;
        } else {
            if (prototype_p)
                *prototype_p = JSVAL_TO_OBJECT(value);
            if (constructor_p)
                *constructor_p = constructor;

            return JS_TRUE;
        }
    }

    g_irepository_require(NULL, "GLib", "2.0", 0, NULL);
    glib_error_info = (GIBoxedInfo*) g_irepository_find_by_name(NULL, "GLib", "Error");
    parent_proto = gjs_lookup_boxed_prototype(context, glib_error_info);
    g_base_info_unref((GIBaseInfo*)glib_error_info);

    prototype = gjs_init_class_dynamic(context, in_object,
                                          parent_proto,
                                          g_base_info_get_namespace( (GIBaseInfo*) info),
                                          constructor_name,
                                          &gjs_error_class,
                                          gjs_error_constructor,
                                          /* number of constructor args (less can be passed) */
                                          1,
                                          /* props of prototype */
                                          &gjs_error_proto_props[0],
                                          /* funcs of prototype */
                                          &gjs_error_proto_funcs[0],
                                          /* props of constructor, MyConstructor.myprop */
                                          NULL,
                                          /* funcs of constructor, MyConstructor.myfunc() */
                                          &gjs_error_constructor_funcs[0]);
    if (prototype == NULL) {
        gjs_log_exception(context, NULL);
        gjs_fatal("Can't init class %s", constructor_name);
    }

    g_assert(gjs_object_has_property(context, in_object, constructor_name));

    GJS_INC_COUNTER(gerror);
    priv = g_slice_new0(Error);
    priv->info = info;
    g_base_info_ref( (GIBaseInfo*) priv->info);
    priv->domain = g_quark_from_string (g_enum_info_get_error_domain(priv->info));

    JS_SetPrivate(context, prototype, priv);

    gjs_debug(GJS_DEBUG_GBOXED, "Defined class %s prototype is %p class %p in object %p",
              constructor_name, prototype, JS_GET_CLASS(context, prototype), in_object);

    constructor = NULL;
    gjs_object_get_property(context, in_object, constructor_name, &value);
    if (!JSVAL_IS_VOID(value)) {
        if (!JSVAL_IS_OBJECT(value)) {
            gjs_throw(context, "Property '%s' does not look like a constructor",
                      constructor_name);
            return JS_FALSE;
        }
    }

    constructor = JSVAL_TO_OBJECT(value);

    gjs_define_enum_values(context, constructor, priv->info);

    if (constructor_p)
        *constructor_p = constructor;

    if (prototype_p)
        *prototype_p = prototype;

    return JS_TRUE;
}
コード例 #12
0
ファイル: boxed.c プロジェクト: Katyunechka/gjs
JSBool
gjs_define_boxed_class(JSContext    *context,
                          JSObject     *in_object,
                          GIBoxedInfo  *info,
                          JSObject    **constructor_p,
                          JSObject    **prototype_p)
{
    const char *constructor_name;
    JSObject *prototype;
    JSObject *constructor;
    jsval value;
    Boxed *priv;

    /* See the comment in gjs_define_object_class() for an
     * explanation of how this all works; Boxed is pretty much the
     * same as Object.
     */

    constructor_name = g_base_info_get_name( (GIBaseInfo*) info);

    if (gjs_object_get_property(context, in_object, constructor_name, &value)) {
        JSObject *constructor;

        if (!JSVAL_IS_OBJECT(value)) {
            gjs_throw(context, "Existing property '%s' does not look like a constructor",
                      constructor_name);
            return JS_FALSE;
        }

        constructor = JSVAL_TO_OBJECT(value);

        gjs_object_get_property(context, constructor, "prototype", &value);
        if (!JSVAL_IS_OBJECT(value)) {
            gjs_throw(context, "boxed %s prototype property does not appear to exist or has wrong type", constructor_name);
            return JS_FALSE;
        } else {
            if (prototype_p)
                *prototype_p = JSVAL_TO_OBJECT(value);
            if (constructor_p)
                *constructor_p = constructor;

            return JS_TRUE;
        }
    }

    if (!gjs_init_class_dynamic(context, in_object,
                                NULL, /* parent prototype */
                                g_base_info_get_namespace( (GIBaseInfo*) info),
                                constructor_name,
                                &gjs_boxed_class,
                                gjs_boxed_constructor, 1,
                                /* props of prototype */
                                &gjs_boxed_proto_props[0],
                                /* funcs of prototype */
                                &gjs_boxed_proto_funcs[0],
                                /* props of constructor, MyConstructor.myprop */
                                NULL,
                                /* funcs of constructor, MyConstructor.myfunc() */
                                NULL,
                                &prototype,
                                &constructor)) {
        gjs_log_exception(context, NULL);
        gjs_fatal("Can't init class %s", constructor_name);
    }

    GJS_INC_COUNTER(boxed);
    priv = g_slice_new0(Boxed);
    priv->info = info;
    boxed_fill_prototype_info(priv);

    g_base_info_ref( (GIBaseInfo*) priv->info);
    priv->gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo*) priv->info);
    JS_SetPrivate(context, prototype, priv);

    gjs_debug(GJS_DEBUG_GBOXED, "Defined class %s prototype is %p class %p in object %p",
              constructor_name, prototype, JS_GET_CLASS(context, prototype), in_object);

    priv->can_allocate_directly = struct_is_simple (priv->info);

    define_boxed_class_fields (context, priv, prototype);
    gjs_define_static_methods (context, constructor, priv->gtype, priv->info);

    value = OBJECT_TO_JSVAL(gjs_gtype_create_gtype_wrapper(context, priv->gtype));
    JS_DefineProperty(context, constructor, "$gtype", value,
                      NULL, NULL, JSPROP_PERMANENT);

    if (constructor_p)
        *constructor_p = constructor;

    if (prototype_p)
        *prototype_p = prototype;

    return JS_TRUE;
}
コード例 #13
0
ファイル: context.c プロジェクト: RavetcoFX/cjs
gboolean
gjs_context_eval(GjsContext *js_context,
                 const char   *script,
                 gssize        script_len,
                 const char   *filename,
                 int          *exit_status_p,
                 GError      **error)
{
    int line_number;
    jsval retval;
    gboolean success;
    gunichar2 *u16_script;
    glong u16_script_len;

    g_object_ref(G_OBJECT(js_context));

    if (exit_status_p)
        *exit_status_p = 1; /* "Failure" (like a shell script) */

    /* whether we evaluated the script OK; not related to whether
     * script returned nonzero. We set GError if success = FALSE
     */
    success = TRUE;

    /* handle scripts with UNIX shebangs */
    line_number = 1;
    if (script != NULL && script[0] == '#' && script[1] == '!') {
        const char *s;

        s = (const char *) strstr (script, "\n");
        if (s != NULL) {
            if (script_len > 0)
                script_len -= (s + 1 - script);
            script = s + 1;
            line_number = 2;
        }
    }

    if ((u16_script = g_utf8_to_utf16 (script, script_len, NULL, &u16_script_len, error)) == NULL)
        return FALSE;
    g_assert (u16_script_len < G_MAXUINT);

    /* log and clear exception if it's set (should not be, normally...) */
    if (gjs_log_exception(js_context->context,
                             NULL)) {
        gjs_debug(GJS_DEBUG_CONTEXT,
                  "Exception was set prior to JS_EvaluateScript()");
    }

    /* JS_EvaluateScript requires a request even though it sort of seems like
     * it means we're always in a request?
     */
    gjs_runtime_push_context(js_context->runtime, js_context->context);
    JS_BeginRequest(js_context->context);

    retval = JSVAL_VOID;
    if (!JS_EvaluateUCScript(js_context->context,
                             js_context->global,
                             (const jschar*)u16_script,
                             (guint) u16_script_len,
                             filename,
                             line_number,
                             &retval)) {
        char *message;

        gjs_debug(GJS_DEBUG_CONTEXT,
                  "Script evaluation failed");

        /* if message is NULL then somehow exception wasn't set */
        message = NULL;
        gjs_log_exception(js_context->context,
                             &message);
        if (message) {
            g_set_error(error,
                        GJS_ERROR,
                        GJS_ERROR_FAILED,
                        "%s", message);
            g_free(message);
        } else {
            gjs_debug(GJS_DEBUG_CONTEXT,
                      "JS_EvaluateScript() failed but no exception message?");
            g_set_error(error,
                        GJS_ERROR,
                        GJS_ERROR_FAILED,
                        "JS_EvaluateScript() failed but no exception message?");
        }

        success = FALSE;
    }
    g_free (u16_script);

    gjs_debug(GJS_DEBUG_CONTEXT,
              "Script evaluation succeeded");

    if (gjs_log_exception(js_context->context, NULL)) {
        g_set_error(error,
                    GJS_ERROR,
                    GJS_ERROR_FAILED,
                    "Exception was set even though JS_EvaluateScript() returned true - did you gjs_throw() but not return false somewhere perhaps?");
        success = FALSE;
    }

    if (success && exit_status_p) {
        if (JSVAL_IS_INT(retval)) {
            int code;
            if (JS_ValueToInt32(js_context->context, retval, &code)) {

                gjs_debug(GJS_DEBUG_CONTEXT,
                          "Script returned integer code %d", code);

                *exit_status_p = code;
            }
        } else {
            /* Assume success if no integer was returned */
            *exit_status_p = 0;
        }
    }

    JS_EndRequest(js_context->context);
    gjs_runtime_pop_context(js_context->runtime);

    g_object_unref(G_OBJECT(js_context));

    return success;
}
コード例 #14
0
ファイル: keep-alive.c プロジェクト: sjokkis/gjs
JSObject*
gjs_keep_alive_new(JSContext *context)
{
    JSObject *keep_alive;
    JSObject *global;

    g_assert(context != NULL);

    JS_BeginRequest(context);

    /* put constructor in the global namespace */
    global = JS_GetGlobalObject(context);

    g_assert(global != NULL);

    if (!gjs_object_has_property(context, global, gjs_keep_alive_class.name)) {
        JSObject *prototype;

        gjs_debug(GJS_DEBUG_KEEP_ALIVE,
                  "Initializing keep-alive class in context %p global %p",
                  context, global);

        prototype = JS_InitClass(context, global,
                                 /* parent prototype JSObject* for
                                  * prototype; NULL for
                                  * Object.prototype
                                  */
                                 NULL,
                                 &gjs_keep_alive_class,
                                 /* constructor for instances (NULL for
                                  * none - just name the prototype like
                                  * Math - rarely correct)
                                  */
                                 keep_alive_constructor,
                                 /* number of constructor args */
                                 0,
                                 /* props of prototype */
                                 &gjs_keep_alive_proto_props[0],
                                 /* funcs of prototype */
                                 &gjs_keep_alive_proto_funcs[0],
                                 /* props of constructor, MyConstructor.myprop */
                                 NULL,
                                 /* funcs of constructor, MyConstructor.myfunc() */
                                 NULL);
        if (prototype == NULL)
            gjs_fatal("Can't init class %s", gjs_keep_alive_class.name);

        g_assert(gjs_object_has_property(context, global, gjs_keep_alive_class.name));

        gjs_debug(GJS_DEBUG_KEEP_ALIVE, "Initialized class %s prototype %p",
                  gjs_keep_alive_class.name, prototype);
    }

    gjs_debug(GJS_DEBUG_KEEP_ALIVE,
              "Creating new keep-alive object for context %p global %p",
              context, global);

    /* Without the "global" parent object, this craters inside of
     * xulrunner because in jsobj.c:js_ConstructObject it looks up
     * VOID as the constructor.  Exploring in gdb, it is walking up
     * the scope chain in a way that involves scary xpconnect-looking
     * stuff. Having "global" as parent seems to fix it. But, it would
     * not hurt to understand this better.
     */
    keep_alive = JS_ConstructObject(context, &gjs_keep_alive_class, NULL, global);
    if (keep_alive == NULL) {
        gjs_log_exception(context, NULL);
        gjs_fatal("Failed to create keep_alive object");
    }

    JS_EndRequest(context);

    return keep_alive;
}
コード例 #15
0
ファイル: value.c プロジェクト: Katyunechka/gjs
static void
closure_marshal(GClosure        *closure,
                GValue          *return_value,
                guint            n_param_values,
                const GValue    *param_values,
                gpointer         invocation_hint,
                gpointer         marshal_data)
{
    JSRuntime *runtime;
    JSContext *context;
    int argc;
    jsval *argv;
    jsval rval;
    int i;
    GSignalQuery signal_query = { 0, };

    gjs_debug_marshal(GJS_DEBUG_GCLOSURE,
                      "Marshal closure %p",
                      closure);

    if (!gjs_closure_is_valid(closure)) {
        /* We were destroyed; become a no-op */
        return;
    }

    runtime = gjs_closure_get_runtime(closure);
    context = gjs_runtime_get_current_context(runtime);
    JS_BeginRequest(context);

    argc = n_param_values;
    argv = g_newa(jsval, n_param_values);
    rval = JSVAL_VOID;

    gjs_set_values(context, argv, argc, JSVAL_VOID);
    gjs_root_value_locations(context, argv, argc);
    JS_AddValueRoot(context, &rval);

    if (marshal_data) {
        /* we are used for a signal handler */
        guint signal_id;

        signal_id = GPOINTER_TO_UINT(marshal_data);

        g_signal_query(signal_id, &signal_query);

        if (!signal_query.signal_id) {
            gjs_debug(GJS_DEBUG_GCLOSURE,
                      "Signal handler being called on invalid signal");
            goto cleanup;
        }

        if (signal_query.n_params + 1 != n_param_values) {
            gjs_debug(GJS_DEBUG_GCLOSURE,
                      "Signal handler being called with wrong number of parameters");
            goto cleanup;
        }
    }

    for (i = 0; i < argc; ++i) {
        const GValue *gval = &param_values[i];
        gboolean no_copy;

        no_copy = FALSE;

        if (i >= 1 && signal_query.signal_id) {
            no_copy = (signal_query.param_types[i - 1] & G_SIGNAL_TYPE_STATIC_SCOPE) != 0;
        }

        if (!gjs_value_from_g_value_internal(context, &argv[i], gval, no_copy, &signal_query, i)) {
            gjs_debug(GJS_DEBUG_GCLOSURE,
                      "Unable to convert arg %d in order to invoke closure",
                      i);
            gjs_log_exception(context, NULL);
            goto cleanup;
        }
    }

    gjs_closure_invoke(closure, argc, argv, &rval);

    if (return_value != NULL) {
        if (JSVAL_IS_VOID(rval)) {
            /* something went wrong invoking, error should be set already */
            goto cleanup;
        }

        if (!gjs_value_to_g_value(context, rval, return_value)) {
            gjs_debug(GJS_DEBUG_GCLOSURE,
                      "Unable to convert return value when invoking closure");
            gjs_log_exception(context, NULL);
            goto cleanup;
        }
    }

 cleanup:
    gjs_unroot_value_locations(context, argv, argc);
    JS_RemoveValueRoot(context, &rval);
    JS_EndRequest(context);
}