static JSObject* importer_new(JSContext *context) { JSObject *importer; Importer *priv; JSObject *global; (void) priv; global = gjs_get_import_global(context); if (!gjs_object_has_property(context, global, gjs_importer_class.name)) { JSObject *prototype; prototype = JS_InitClass(context, global, /* parent prototype JSObject* for * prototype; NULL for * Object.prototype */ NULL, &gjs_importer_class, /* constructor for instances (NULL for * none - just name the prototype like * Math - rarely correct) */ gjs_importer_constructor, /* number of constructor args */ 0, /* props of prototype */ &gjs_importer_proto_props[0], /* funcs of prototype */ &gjs_importer_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_importer_class.name); g_assert(gjs_object_has_property(context, global, gjs_importer_class.name)); gjs_debug(GJS_DEBUG_IMPORTER, "Initialized class %s prototype %p", gjs_importer_class.name, prototype); } importer = JS_NewObject(context, &gjs_importer_class, NULL, global); if (importer == NULL) gjs_fatal("No memory to create importer importer"); priv = g_slice_new0(Importer); GJS_INC_COUNTER(importer); g_assert(priv_from_js(context, importer) == NULL); JS_SetPrivate(importer, priv); gjs_debug_lifecycle(GJS_DEBUG_IMPORTER, "importer constructor, obj %p priv %p", importer, priv); return importer; }
static JSObject* gjs_keep_alive_create_in_global(JSContext *context) { JSObject *keep_alive; JSObject *global; JS_BeginRequest(context); global = JS_GetGlobalObject(context); keep_alive = gjs_keep_alive_new(context); if (!JS_DefineProperty(context, global, GLOBAL_KEEP_ALIVE_NAME, OBJECT_TO_JSVAL(keep_alive), NULL, NULL, /* No ENUMERATE since this is a hidden * implementation detail kind of property */ JSPROP_READONLY | JSPROP_PERMANENT)) gjs_fatal("no memory to define keep_alive property"); JS_EndRequest(context); return keep_alive; }
/** * gjs_runtime_destroy: * @runtime: a #JSRuntime * * Calls JS_DestroyRuntime() on runtime and frees data allocated by * gjs_runtime_init(); these are unified into a single call because we * need to order things so that the allocated data is cleaned up * after JS_DestroyRuntime(). We might have finalizers run by * JS_DestroyRuntime() that rely on the information stored in the data, * such as the dynamic class structs. * * This should only be called by GJS, not by applications. */ void gjs_runtime_destroy(JSRuntime *runtime) { RuntimeData *rd; void *key; void *value; rd = JS_GetRuntimePrivate(runtime); if (rd->context_stack != NULL || rd->current_frame.depth != 0) gjs_fatal("gjs_runtime_destroy() called during gjs_push_context()"); gjs_debug(GJS_DEBUG_CONTEXT, "Destroying JS runtime"); JS_DestroyRuntime(runtime); gjs_debug(GJS_DEBUG_CONTEXT, "Destroying any remaining dataset items on runtime"); while (gjs_g_hash_table_remove_one(rd->dynamic_classes, &key, &value)) { JSClass *clasp = value; gjs_debug(GJS_DEBUG_GREPO, "Finalizing dynamic class '%s'", clasp->name); g_free( (char*) clasp->name); /* we know we malloc'd the char* even though it's const */ g_slice_free(DynamicJSClass, (DynamicJSClass*) clasp); } g_hash_table_destroy(rd->dynamic_classes); g_slice_free(RuntimeData, rd); }
JSObject* gjs_define_importer(JSContext *context, JSObject *in_object, const char *importer_name, const char **initial_search_path, gboolean add_standard_search_path) { JSObject *importer; char **paths[2] = {0}; char **search_path; paths[0] = (char**)initial_search_path; if (add_standard_search_path) { /* Stick the "standard" shared search path after the provided one. */ paths[1] = (char**)gjs_get_search_path(); } search_path = gjs_g_strv_concat(paths, 2); importer = importer_new(context); /* API users can replace this property from JS, is the idea */ if (!gjs_define_string_array(context, importer, "searchPath", -1, (const char **)search_path, /* settable (no READONLY) but not deleteable (PERMANENT) */ JSPROP_PERMANENT | JSPROP_ENUMERATE)) gjs_fatal("no memory to define importer search path prop"); g_strfreev(search_path); if (!define_meta_properties(context, importer, importer_name, in_object)) gjs_fatal("failed to define meta properties on importer"); if (!JS_DefineProperty(context, in_object, importer_name, OBJECT_TO_JSVAL(importer), NULL, NULL, GJS_MODULE_PROP_FLAGS)) gjs_fatal("no memory to define importer property"); gjs_debug(GJS_DEBUG_IMPORTER, "Defined importer '%s' %p in %p", importer_name, importer, in_object); return importer; }
static RuntimeData* get_data_from_runtime(JSRuntime *runtime) { RuntimeData *rd; rd = JS_GetRuntimePrivate(runtime); if (G_UNLIKELY(rd == NULL)) gjs_fatal("JSRuntime not initialized for use with GJS"); return rd; }
/** * gjs_runtime_set_default_context: * @runtime: a #JSRuntime * @context: a #JSContext * * Makes @context the default context for @runtime. The default context is the * context used for executing callbacks when no other context is active. * This generally should only be called by GJS - GJS sets the default context * when #GjsContext creates a runtime, and subsequent calls to this function * will produce an error. */ void gjs_runtime_set_default_context(JSRuntime *runtime, JSContext *context) { RuntimeData *rd; rd = get_data_from_runtime(runtime); if (rd->context_stack != NULL || rd->current_frame.depth != 0) gjs_fatal("gjs_runtime_set_default_context() called during gjs_push_context()"); if (context != NULL) { if (rd->default_context != NULL) gjs_fatal("gjs_runtime_set_default_context() called twice on the same JSRuntime"); rd->default_context = context; rd->current_frame.context = context; rd->import_global = JS_GetGlobalObject(rd->default_context); } else { rd->default_context = NULL; rd->current_frame.context = NULL; rd->import_global = NULL; } }
jsval gjs_date_from_time_t (JSContext *context, time_t time) { JSObject *date; JSClass *date_class; JSObject *date_constructor; jsval date_prototype; jsval args[1]; jsval result; JS_BeginRequest(context); if (!JS_EnterLocalRootScope(context)) return JSVAL_VOID; if (!JS_GetClassObject(context, JS_GetGlobalObject(context), JSProto_Date, &date_constructor)) gjs_fatal("Failed to lookup Date prototype"); if (!JS_GetProperty(context, date_constructor, "prototype", &date_prototype)) gjs_fatal("Failed to get prototype from Date constructor"); date_class = JS_GET_CLASS(context, JSVAL_TO_OBJECT (date_prototype)); if (!JS_NewNumberValue(context, ((double) time) * 1000, &(args[0]))) gjs_fatal("Failed to convert time_t to number"); date = JS_ConstructObjectWithArguments(context, date_class, NULL, NULL, 1, args); result = OBJECT_TO_JSVAL(date); JS_LeaveLocalRootScope(context); JS_EndRequest(context); return result; }
/** * gjs_runtime_pop_context: * @runtime: a #JSRuntime * * Pops a context pushed onto the stack of active contexts by * gjs_runtime_push_context(). */ void gjs_runtime_pop_context(JSRuntime *runtime) { RuntimeData *rd; rd = get_data_from_runtime(runtime); if (rd->current_frame.depth == 0) { if (rd->context_stack == NULL) gjs_fatal("gjs_runtime_pop_context() called more times than gjs_runtime_push_context()"); rd->current_frame = *(ContextFrame *)rd->context_stack->data; g_slice_free(ContextFrame, rd->context_stack->data); rd->context_stack = g_slist_delete_link(rd->context_stack, rd->context_stack); } else { rd->current_frame.depth--; } }
/** * gjs_runtime_init: * @runtime: a #JSRuntime * * Initializes a #JSRuntime for use with GJS * * This should only be called by GJS, not by applications. */ void gjs_runtime_init(JSRuntime *runtime) { RuntimeData *rd; /* If we went back to supporting foreign contexts, we couldn't use * JS_SetRuntimePrivate() because the runtime's owner might * already be using it. A simple solution would be to just store * the runtime data in a global variable - multiple copies of GJS * in the same process at the same time have issues anyways * because of limitations of GObject toggle references - if two * separate entities toggle reference an object it will leak. */ if (JS_GetRuntimePrivate(runtime) != NULL) gjs_fatal("JSRuntime already initialized or private data in use by someone else"); rd = g_slice_new0(RuntimeData); rd->dynamic_classes = g_hash_table_new(g_direct_hash, g_direct_equal); JS_SetRuntimePrivate(runtime, rd); }
void gjs_keep_alive_remove_global_child(JSContext *context, GjsUnrootedFunc notify, JSObject *child, void *data) { JSObject *keep_alive; JS_BeginRequest(context); keep_alive = gjs_keep_alive_get_global(context); if (!keep_alive) gjs_fatal("no keep_alive property on the global object, have you " "previously added this child?"); gjs_keep_alive_remove_child(context, gjs_keep_alive_get_global(context), notify, child, data); JS_EndRequest(context); }
JSObject* gjs_keep_alive_get_for_import_global(JSContext *context) { JSObject *global; JSObject *keep_alive; global = gjs_get_import_global(context); g_assert(global != NULL); JS_BeginRequest(context); keep_alive = gjs_keep_alive_get_from_parent(context, global); if (!keep_alive) keep_alive = gjs_keep_alive_create_in_parent(context, global); if (!keep_alive) gjs_fatal("could not create keep_alive on global object, no memory?"); JS_EndRequest(context); return keep_alive; }
void gjs_keep_alive_add_global_child(JSContext *context, GjsUnrootedFunc notify, JSObject *child, void *data) { JSObject *keep_alive; JS_BeginRequest(context); keep_alive = gjs_keep_alive_get_global(context); if (!keep_alive) keep_alive = gjs_keep_alive_create_in_global(context); if (!keep_alive) gjs_fatal("could not create keep_alive on global object, no memory?"); gjs_keep_alive_add_child(context, keep_alive, notify, child, data); JS_EndRequest(context); }
JSObject* gjs_keep_alive_get_for_load_context(JSRuntime *runtime) { JSContext *context; JSObject *keep_alive; context = gjs_runtime_get_load_context(runtime); g_assert(context != NULL); JS_BeginRequest(context); keep_alive = gjs_keep_alive_get_global(context); if (!keep_alive) keep_alive = gjs_keep_alive_create_in_global(context); if (!keep_alive) gjs_fatal("could not create keep_alive on global object, no memory?"); JS_EndRequest(context); return keep_alive; }
JSBool gjs_define_param_class(JSContext *context, JSObject *in_object, JSObject **prototype_p) { const char *constructor_name; JSObject *prototype; jsval value; JSObject *constructor; constructor_name = "ParamSpec"; gjs_object_get_property(context, in_object, constructor_name, &value); if (!JSVAL_IS_VOID(value)) { 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, "prototype property does not appear to exist or has wrong type"); return JS_FALSE; } else { if (prototype_p) *prototype_p = JSVAL_TO_OBJECT(value); return JS_TRUE; } return JS_TRUE; } /* we could really just use JS_InitClass for this since we have one class instead of * N classes on-demand. But, this deals with namespacing and such for us. */ prototype = gjs_init_class_dynamic(context, in_object, /* parent prototype JSObject* for * prototype; NULL for * Object.prototype */ NULL, "GObject", constructor_name, &gjs_param_class, /* constructor for instances (NULL for * none - just name the prototype like * Math - rarely correct) */ gjs_param_constructor, /* number of constructor args */ 0, /* props of prototype */ &gjs_param_proto_props[0], /* funcs of prototype */ &gjs_param_proto_funcs[0], /* props of constructor, MyConstructor.myprop */ NULL, /* funcs of constructor, MyConstructor.myfunc() */ gjs_param_constructor_funcs); if (prototype == NULL) gjs_fatal("Can't init class %s", constructor_name); constructor = NULL; gjs_object_get_property(context, in_object, constructor_name, &value); if (value != JSVAL_VOID) { 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); value = OBJECT_TO_JSVAL(gjs_gtype_create_gtype_wrapper(context, G_TYPE_PARAM)); JS_DefineProperty(context, constructor, "$gtype", value, NULL, NULL, JSPROP_PERMANENT); if (prototype_p) *prototype_p = prototype; gjs_debug(GJS_DEBUG_GPARAM, "Defined class %s prototype is %p class %p in object %p", constructor_name, prototype, JS_GET_CLASS(context, prototype), in_object); return JS_TRUE; }
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; }
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; }
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; }
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; }
JSBool gjs_define_interface_class(JSContext *context, JSObject *in_object, GIInterfaceInfo *info, JSObject **prototype_p) { Interface *priv; const char *constructor_name; JSObject *constructor; JSObject *prototype; jsval value; constructor_name = g_base_info_get_name((GIBaseInfo*)info); gjs_object_get_property(context, in_object, constructor_name, &value); if (!JSVAL_IS_VOID(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, "prototype property does not appear to exist or has wrong type"); return JS_FALSE; } else { if (prototype_p) *prototype_p = JSVAL_TO_OBJECT(value); return JS_TRUE; } return JS_TRUE; } if (!gjs_init_class_dynamic(context, in_object, NULL, g_base_info_get_namespace((GIBaseInfo*)info), constructor_name, &gjs_interface_class, gjs_interface_constructor, 0, /* props of prototype */ &gjs_interface_proto_props[0], /* funcs of prototype */ &gjs_interface_proto_funcs[0], /* props of constructor, MyConstructor.myprop */ NULL, /* funcs of constructor, MyConstructor.myfunc() */ NULL, &prototype, &constructor)) { gjs_fatal("Can't init class %s", constructor_name); } GJS_INC_COUNTER(interface); priv = g_slice_new0(Interface); priv->info = info; priv->gtype = g_registered_type_info_get_g_type(priv->info); g_base_info_ref((GIBaseInfo*)priv->info); JS_SetPrivate(context, prototype, priv); 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 (prototype_p) *prototype_p = prototype; return JS_TRUE; }
static GObject* gjs_context_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_params) { GObject *object; GjsContext *js_context; guint32 options_flags; JSVersion js_version; object = (* G_OBJECT_CLASS (gjs_context_parent_class)->constructor) (type, n_construct_properties, construct_params); js_context = GJS_CONTEXT(object); if (js_context->runtime == NULL) { js_context->runtime = JS_NewRuntime(32*1024*1024 /* max bytes */); if (js_context->runtime == NULL) gjs_fatal("Failed to create javascript runtime"); JS_SetGCParameter(js_context->runtime, JSGC_MAX_BYTES, 0xffffffff); js_context->we_own_runtime = TRUE; gjs_runtime_init(js_context->runtime); } js_context->context = JS_NewContext(js_context->runtime, 8192 /* stack chunk size */); if (js_context->context == NULL) gjs_fatal("Failed to create javascript context"); JS_BeginRequest(js_context->context); /* same as firefox, see discussion at * https://bugzilla.mozilla.org/show_bug.cgi?id=420869 */ JS_SetScriptStackQuota(js_context->context, 100*1024*1024); /* JSOPTION_DONT_REPORT_UNCAUGHT: Don't send exceptions to our * error report handler; instead leave them set. This allows us * to get at the exception object. * * JSOPTION_STRICT: Report warnings to error reporter function. */ options_flags = JSOPTION_DONT_REPORT_UNCAUGHT | JSOPTION_STRICT; if (!g_getenv("GJS_DISABLE_JIT")) { gjs_debug(GJS_DEBUG_CONTEXT, "Enabling JIT"); options_flags |= JSOPTION_METHODJIT; } JS_SetOptions(js_context->context, JS_GetOptions(js_context->context) | options_flags); JS_SetLocaleCallbacks(js_context->context, &gjs_locale_callbacks); JS_SetErrorReporter(js_context->context, gjs_error_reporter); /* set ourselves as the private data */ JS_SetContextPrivate(js_context->context, js_context); js_version = JS_StringToVersion(js_context->jsversion_string); /* It doesn't make sense to throw here; just use the default if we * don't know. */ if (js_version == JSVERSION_UNKNOWN) js_version = JSVERSION_DEFAULT; /* Set the version if we need to. */ if (js_version != JSVERSION_DEFAULT && JS_GetVersion(js_context->context) != js_version) { gjs_debug(GJS_DEBUG_CONTEXT, "Changing JavaScript version to %s from %s", JS_VersionToString(js_version), JS_VersionToString(JS_GetVersion(js_context->context))); JS_SetVersion(js_context->context, js_version); } if (!gjs_init_context_standard(js_context->context)) gjs_fatal("Failed to initialize context"); js_context->global = JS_GetGlobalObject(js_context->context); if (!JS_DefineProperty(js_context->context, js_context->global, "window", OBJECT_TO_JSVAL(js_context->global), NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT)) gjs_fatal("No memory to export global object as 'window'"); /* Define a global function called log() */ if (!JS_DefineFunction(js_context->context, js_context->global, "log", (JSNative)gjs_log, 1, GJS_MODULE_PROP_FLAGS)) gjs_fatal("Failed to define log function"); if (!JS_DefineFunction(js_context->context, js_context->global, "logError", (JSNative)gjs_log_error, 2, GJS_MODULE_PROP_FLAGS)) gjs_fatal("Failed to define logError function"); /* Define global functions called print() and printerr() */ if (!JS_DefineFunction(js_context->context, js_context->global, "print", (JSNative)gjs_print, 3, GJS_MODULE_PROP_FLAGS)) gjs_fatal("Failed to define print function"); if (!JS_DefineFunction(js_context->context, js_context->global, "printerr", (JSNative)gjs_printerr, 4, GJS_MODULE_PROP_FLAGS)) gjs_fatal("Failed to define printerr function"); /* We need to know what the default context is, since it's the context whose * global object is used to load imported JS modules. We currently say that * it's the context of the runtime's owner, but if we needed to support * externally created runtimes, we could define it in some other fashion. */ if (js_context->we_own_runtime) { gjs_runtime_set_default_context(js_context->runtime, js_context->context); } else { if (gjs_runtime_get_default_context(js_context->runtime) == NULL) gjs_fatal("GjsContext created for a runtime not owned by GJS"); } /* We create the global-to-runtime root importer with the * passed-in search path. If someone else already created * the root importer, this is a no-op. */ if (!gjs_create_root_importer(js_context->context, js_context->search_path ? (const char**) js_context->search_path : NULL, TRUE)) gjs_fatal("Failed to create root importer"); /* Now copy the global root importer (which we just created, * if it didn't exist) to our global object */ if (!gjs_define_root_importer(js_context->context, js_context->global, "imports")) gjs_fatal("Failed to point 'imports' property at root importer"); if (js_context->we_own_runtime) { js_context->profiler = gjs_profiler_new(js_context->runtime); } if (!gjs_is_registered_native_module(js_context->context, NULL, "gi")) gjs_register_native_module("gi", gjs_define_gi_stuff, GJS_NATIVE_SUPPLIES_MODULE_OBJ); /* For GjsDBus */ { char *priv_typelib_dir = g_build_filename (PKGLIBDIR, "girepository-1.0", NULL); g_irepository_prepend_search_path(priv_typelib_dir); g_free (priv_typelib_dir); } if (js_context->gc_notifications_enabled) JS_SetGCCallback(js_context->context, gjs_on_context_gc); JS_EndRequest(js_context->context); g_static_mutex_lock (&contexts_lock); all_contexts = g_list_prepend(all_contexts, object); g_static_mutex_unlock (&contexts_lock); return object; }