JSObject* gjs_param_from_g_param(JSContext *context, GParamSpec *gparam) { JSObject *obj; Param *priv; if (gparam == NULL) return NULL; gjs_debug(GJS_DEBUG_GPARAM, "Wrapping %s '%s' on %s with JSObject", g_type_name(G_TYPE_FROM_INSTANCE((GTypeInstance*) gparam)), gparam->name, g_type_name(gparam->owner_type)); JS::RootedObject proto(context, gjs_lookup_param_prototype(context)); obj = JS_NewObjectWithGivenProto(context, JS_GetClass(proto), proto); GJS_INC_COUNTER(param); priv = g_slice_new0(Param); JS_SetPrivate(obj, priv); priv->gparam = gparam; g_param_spec_ref (gparam); gjs_debug(GJS_DEBUG_GPARAM, "JSObject created with param instance %p type %s", priv->gparam, g_type_name(G_TYPE_FROM_INSTANCE((GTypeInstance*) priv->gparam))); return obj; }
/** * gjs_cairo_path_from_path: * @context: the context * @path: cairo_path_t to attach to the object * * Constructs a pattern wrapper given cairo pattern. * NOTE: This function takes ownership of the path. */ JSObject * gjs_cairo_path_from_path(JSContext *context, cairo_path_t *path) { GjsCairoPath *priv; g_return_val_if_fail(context != NULL, NULL); g_return_val_if_fail(path != NULL, NULL); JS::RootedObject proto(context, gjs_cairo_path_get_proto(context)); JS::RootedObject object(context, JS_NewObjectWithGivenProto(context, &gjs_cairo_path_class, proto)); if (!object) { gjs_throw(context, "failed to create path"); return NULL; } priv = g_slice_new0(GjsCairoPath); g_assert(priv_from_js(context, object) == NULL); JS_SetPrivate(object, priv); priv->context = context; priv->object = object; priv->path = path; return object; }
JSBool js_createStore(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { const char *id; char spath[URL_MAX]; JSBool per_user = 0; if(!JS_ConvertArguments(cx, argc, argv, "s/b", &id, &per_user)) return JS_FALSE; js_plugin_t *jsp = JS_GetPrivate(cx, obj); snprintf(spath, sizeof(spath), "jsstore/%s-%s", jsp->jsp_id, id); js_setting_group_t *jsg = calloc(1, sizeof(js_setting_group_t)); JSObject *robj; jsg->jsg_refcount = 1; jsg->jsg_frozen = 1; jsg->jsg_spath = strdup(spath); jsg->jsg_store = htsmsg_store_load(spath) ?: htsmsg_create_map(); robj = JS_NewObjectWithGivenProto(cx, &setting_group_class, NULL, obj); *rval = OBJECT_TO_JSVAL(robj); JS_SetPrivate(cx, robj, jsg); jsg->jsg_frozen = 0; return JS_TRUE; }
JSBool js_createService(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { const char *title; const char *url; const char *type; const char *icon = NULL; JSObject *robj; JSBool enabled; if (!JS_ConvertArguments(cx, argc, argv, "sssb/s", &title, &url, &type, &enabled, &icon)) return JS_FALSE; js_plugin_t *jsp = JS_GetPrivate(cx, obj); js_service_t *jss = malloc(sizeof(js_service_t)); jss->jss_ref = 2; jss->jss_s = service_create(title, url, type, icon, 0, enabled); LIST_INSERT_HEAD(&jsp->jsp_services, jss, jss_link); robj = JS_NewObjectWithGivenProto(cx, &service_class, NULL, NULL); *rval = OBJECT_TO_JSVAL(robj); JS_SetPrivate(cx, robj, jss); JS_DefineProperty(cx, robj, "enabled", BOOLEAN_TO_JSVAL(enabled), NULL, setEnabled, JSPROP_PERMANENT); JS_DefineFunction(cx, robj, "destroy", destroy, 0, 0); return JS_TRUE; }
JSBool WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp) { // Slim wrappers don't expect to be wrapped, so morph them to fat wrappers // if we're about to wrap one. JSObject *innerObj = JSVAL_TO_OBJECT(v); if (IS_SLIM_WRAPPER(innerObj) && !MorphSlimWrapper(cx, innerObj)) { return ThrowException(NS_ERROR_FAILURE, cx); } JSObject *wrapperObj = JS_NewObjectWithGivenProto(cx, js::Jsvalify(&SOWClass), NULL, parent); if (!wrapperObj) { return JS_FALSE; } *vp = OBJECT_TO_JSVAL(wrapperObj); js::AutoObjectRooter tvr(cx, wrapperObj); if (!JS_SetReservedSlot(cx, wrapperObj, sWrappedObjSlot, v) || !JS_SetReservedSlot(cx, wrapperObj, sFlagsSlot, JSVAL_ZERO)) { return JS_FALSE; } return JS_TRUE; }
JSBool wrapObject(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { JSObject *wrappee; JSObject *resolver; if (!JS_ConvertArguments(cx, argc, argv, "oo", &wrappee, &resolver)) return JS_FALSE; JSObject *wrapper = JS_NewObjectWithGivenProto( cx, &sFlexibleWrapper_JSClass.base, NULL, wrappee ); if (wrapper == NULL) { JS_ReportError(cx, "Creating new wrapper failed."); return JS_FALSE; } if (!JS_SetReservedSlot(cx, wrapper, SLOT_RESOLVER, OBJECT_TO_JSVAL(resolver)) || !JS_SetReservedSlot(cx, wrapper, SLOT_WRAPPEE, OBJECT_TO_JSVAL(wrappee))) return JS_FALSE; *rval = OBJECT_TO_JSVAL(wrapper); return JS_TRUE; }
JSBool XPC_COW_WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp) { JSObject *wrapperObj = JS_NewObjectWithGivenProto(cx, &sXPC_COW_JSClass.base, NULL, parent); if (!wrapperObj) { return JS_FALSE; } *vp = OBJECT_TO_JSVAL(wrapperObj); jsval exposedProps = JSVAL_VOID; JSAutoTempValueRooter tvr(cx, 1, &exposedProps); if (!GetExposedProperties(cx, JSVAL_TO_OBJECT(v), &exposedProps)) { return JS_FALSE; } if (!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sWrappedObjSlot, v) || !JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sFlagsSlot, JSVAL_ZERO) || !JS_SetReservedSlot(cx, wrapperObj, sExposedPropsSlot, exposedProps)) { return JS_FALSE; } return JS_TRUE; }
// static JSObject* DOMProxyHandler::EnsureExpandoObject(JSContext* cx, JSObject* obj) { NS_ASSERTION(IsDOMProxy(obj), "expected a DOM proxy object"); JSObject* expando = GetExpandoObject(obj); if (!expando) { expando = JS_NewObjectWithGivenProto(cx, nullptr, nullptr, js::GetObjectParent(obj)); if (!expando) { return NULL; } XPCWrappedNativeScope* scope = xpc::GetObjectScope(obj); if (!scope->RegisterDOMExpandoObject(obj)) { return NULL; } nsWrapperCache* cache; CallQueryInterface(UnwrapDOMObject<nsISupports>(obj), &cache); cache->SetPreservingWrapper(true); js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, ObjectValue(*expando)); } return expando; }
JSBool js_createSettings(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { const char *title; const char *icon = NULL; const char *desc = NULL; char spath[URL_MAX]; if(!JS_ConvertArguments(cx, argc, argv, "s/ss", &title, &icon, &desc)) return JS_FALSE; js_plugin_t *jsp = JS_GetPrivate(cx, obj); snprintf(spath, sizeof(spath), "plugins/%s", jsp->jsp_id); js_setting_group_t *jsg = calloc(1, sizeof(js_setting_group_t)); JSObject *robj; jsg->jsg_refcount = 2; LIST_INSERT_HEAD(&jsp->jsp_setting_groups, jsg, jsg_link); jsg->jsg_frozen = 1; jsg->jsg_spath = strdup(spath); jsg->jsg_store = htsmsg_store_load(spath) ?: htsmsg_create_map(); jsg->jsg_root = settings_add_dir(settings_apps, _p(title), NULL, icon, desc ? _p(desc) : NULL); robj = JS_NewObjectWithGivenProto(cx, &setting_group_class, NULL, obj); jsg->jsg_val = *rval = OBJECT_TO_JSVAL(robj); JS_AddNamedRoot(cx, &jsg->jsg_val, "jsg"); JS_SetPrivate(cx, robj, jsg); JS_DefineFunctions(cx, robj, setting_functions); jsg->jsg_frozen = 0; return JS_TRUE; }
/** * gjs_cairo_surface_from_surface: * @context: the context * @surface: cairo_surface to attach to the object * * Constructs a surface wrapper given cairo surface. * A reference to @surface will be taken. * */ JSObject * gjs_cairo_surface_from_surface(JSContext *context, cairo_surface_t *surface) { g_return_val_if_fail(context != NULL, NULL); g_return_val_if_fail(surface != NULL, NULL); cairo_surface_type_t type = cairo_surface_get_type(surface); if (type == CAIRO_SURFACE_TYPE_IMAGE) return gjs_cairo_image_surface_from_surface(context, surface); if (type == CAIRO_SURFACE_TYPE_PDF) return gjs_cairo_pdf_surface_from_surface(context, surface); if (type == CAIRO_SURFACE_TYPE_PS) return gjs_cairo_ps_surface_from_surface(context, surface); if (type == CAIRO_SURFACE_TYPE_SVG) return gjs_cairo_svg_surface_from_surface(context, surface); JS::RootedObject proto(context, gjs_cairo_surface_get_proto(context)); JS::RootedObject object(context, JS_NewObjectWithGivenProto(context, &gjs_cairo_surface_class, proto)); if (!object) { gjs_throw(context, "failed to create surface"); return NULL; } gjs_cairo_surface_construct(context, object, surface); return object; }
JSObject * js_object_from_prop(JSContext *cx, prop_t *p) { JSObject *obj = JS_NewObjectWithGivenProto(cx, &prop_bridge_class, NULL, NULL); JS_SetPrivate(cx, obj, prop_ref_inc(p)); return obj; }
JSObject* gjs_boxed_from_c_struct(JSContext *context, GIStructInfo *info, void *gboxed, GjsBoxedCreationFlags flags) { JSObject *obj; JSObject *proto; Boxed *priv; Boxed *proto_priv; if (gboxed == NULL) return NULL; gjs_debug_marshal(GJS_DEBUG_GBOXED, "Wrapping struct %s %p with JSObject", g_base_info_get_name((GIBaseInfo *)info), gboxed); proto = gjs_lookup_boxed_prototype(context, info); proto_priv = priv_from_js(context, proto); obj = JS_NewObjectWithGivenProto(context, JS_GET_CLASS(context, proto), proto, gjs_get_import_global (context)); GJS_INC_COUNTER(boxed); priv = g_slice_new0(Boxed); *priv = *proto_priv; g_base_info_ref( (GIBaseInfo*) priv->info); JS_SetPrivate(context, obj, priv); if ((flags & GJS_BOXED_CREATION_NO_COPY) != 0) { /* we need to create a JS Boxed which references the * original C struct, not a copy of it. Used for * G_SIGNAL_TYPE_STATIC_SCOPE */ priv->gboxed = gboxed; priv->not_owning_gboxed = TRUE; } else { if (priv->gtype != G_TYPE_NONE && g_type_is_a (priv->gtype, G_TYPE_BOXED)) { priv->gboxed = g_boxed_copy(priv->gtype, gboxed); } else if (priv->gtype == G_TYPE_VARIANT) { priv->gboxed = g_variant_ref_sink (gboxed); } else if (priv->can_allocate_directly) { boxed_new_direct(priv); memcpy(priv->gboxed, gboxed, g_struct_info_get_size (priv->info)); } else { gjs_throw(context, "Can't create a Javascript object for %s; no way to copy", g_base_info_get_name( (GIBaseInfo*) priv->info)); } } return obj; }
static JSBool get_nested_interface_object (JSContext *context, JSObject *parent_obj, Boxed *parent_priv, GIFieldInfo *field_info, GITypeInfo *type_info, GIBaseInfo *interface_info, jsval *value) { JSObject *obj; JSObject *proto; int offset; Boxed *priv; Boxed *proto_priv; if (!struct_is_simple ((GIStructInfo *)interface_info)) { gjs_throw(context, "Reading field %s.%s is not supported", g_base_info_get_name ((GIBaseInfo *)parent_priv->info), g_base_info_get_name ((GIBaseInfo *)field_info)); return JS_FALSE; } proto = gjs_lookup_boxed_prototype(context, (GIBoxedInfo*) interface_info); proto_priv = priv_from_js(context, proto); offset = g_field_info_get_offset (field_info); obj = JS_NewObjectWithGivenProto(context, JS_GET_CLASS(context, proto), proto, gjs_get_import_global (context)); if (obj == NULL) return JS_FALSE; GJS_INC_COUNTER(boxed); priv = g_slice_new0(Boxed); JS_SetPrivate(context, obj, priv); priv->info = (GIBoxedInfo*) interface_info; g_base_info_ref( (GIBaseInfo*) priv->info); priv->gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo*) interface_info); priv->can_allocate_directly = proto_priv->can_allocate_directly; /* A structure nested inside a parent object; doesn't have an independent allocation */ priv->gboxed = ((char *)parent_priv->gboxed) + offset; priv->not_owning_gboxed = TRUE; /* We never actually read the reserved slot, but we put the parent object * into it to hold onto the parent object. */ JS_SetReservedSlot(context, obj, 0, OBJECT_TO_JSVAL (parent_obj)); *value = OBJECT_TO_JSVAL(obj); return JS_TRUE; }
JSObject* ScriptInterface::CreateCustomObject(const std::string& typeName) const { std::map<std::string, CustomType>::const_iterator it = m_CustomObjectTypes.find(typeName); if (it == m_CustomObjectTypes.end()) throw PSERROR_Scripting_TypeDoesNotExist(); JS::RootedObject prototype(m->m_cx, it->second.m_Prototype.get()); return JS_NewObjectWithGivenProto(m->m_cx, it->second.m_Class, prototype); }
static JSBool js_appendItem0(JSContext *cx, js_model_t *model, prop_t *parent, const char *url, const char *type, JSObject *metaobj, jsval *data, jsval *rval, int enabled, const char *metabind) { prop_t *item = prop_create_root(NULL); if(url != NULL) prop_set_string(prop_create(item, "url"), url); if(data != NULL) js_prop_set_from_jsval(cx, prop_create(item, "data"), *data); *rval = JSVAL_VOID; if(metabind != NULL) metadb_bind_url_to_prop(NULL, metabind, item); if(type != NULL) { prop_set_string(prop_create(item, "type"), type); if(metaobj) js_prop_from_object(cx, metaobj, prop_create(item, "metadata")); } else if(url != NULL) { if(backend_resolve_item(url, item)) { prop_destroy(item); return JS_TRUE; } } prop_set_int(prop_create(item, "enabled"), enabled); prop_t *p = prop_ref_inc(item); if(prop_set_parent(item, parent)) { prop_destroy(item); prop_ref_dec(p); } else { JSObject *robj = JS_NewObjectWithGivenProto(cx, &item_class, JSVAL_TO_OBJECT(model->jm_item_proto), NULL); *rval = OBJECT_TO_JSVAL(robj); js_item_t *ji = calloc(1, sizeof(js_item_t)); ji->ji_model = model; ji->ji_root = p; LIST_INSERT_HEAD(&model->jm_items, ji, ji_link); JS_SetPrivate(cx, robj, ji); ji->ji_enable_set_property = 1; } return JS_TRUE; }
static JSBool AfxGlobal_newAfxGlImage(JSContext *cx, unsigned argc, JS::Value *vp) { JSObject *obj = JS_NewObjectWithGivenProto(cx, &AfxGlImage_class, NULL, JS_GetGlobalForScopeChain(cx)); JS_DefineFunctions(cx, obj, AfxGlImage_functions); JS_SetPrivate(obj, new AfxGlImage()); JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj)); return JS_TRUE; }
JSObject* gjs_error_from_gerror(JSContext *context, GError *gerror, gboolean add_stack) { JSObject *obj; JSObject *proto; Error *priv; Error *proto_priv; GIEnumInfo *info; if (gerror == NULL) return NULL; info = find_error_domain_info(gerror->domain); if (!info) { /* We don't have error domain metadata */ /* Marshal the error as a plain GError */ GIBaseInfo *glib_boxed; JSObject *retval; glib_boxed = g_irepository_find_by_name(NULL, "GLib", "Error"); retval = gjs_boxed_from_c_struct(context, glib_boxed, gerror, 0); g_base_info_unref(glib_boxed); return retval; } gjs_debug_marshal(GJS_DEBUG_GBOXED, "Wrapping struct %s %p with JSObject", g_base_info_get_name((GIBaseInfo *)info), gboxed); proto = gjs_lookup_error_prototype(context, info); proto_priv = priv_from_js(context, proto); obj = JS_NewObjectWithGivenProto(context, JS_GET_CLASS(context, proto), proto, gjs_get_import_global (context)); GJS_INC_COUNTER(gerror); priv = g_slice_new0(Error); JS_SetPrivate(context, obj, priv); priv->info = info; priv->domain = proto_priv->domain; g_base_info_ref( (GIBaseInfo*) priv->info); priv->gerror = g_error_copy(gerror); if (add_stack) define_error_properties(context, obj); return obj; }
static void js_txn_deadlock(JSContext *cx, js_db_t *jd) { if(JS_IsExceptionPending(cx)) return; if(jd->jd_debug) TRACE(TRACE_DEBUG, "JS", "Raising deadlock exception"); JSObject *obj = JS_NewObjectWithGivenProto(cx, &db_deadlock_exn, NULL, NULL); JS_SetPendingException(cx, OBJECT_TO_JSVAL(obj)); }
// Because of the drastically different ways that same- and cross-origin XOWs // work, we have to call JS_ClearScope when a XOW changes from being same- // origin to cross-origin. Normally, there are defined places in Gecko where // this happens and they notify us. However, UniversalXPConnect causes the // same transition without any notifications. We could try to detect when this // happens, but doing so would require calling JS_ClearScope from random // hooks, which is bad. // // The compromise is the UXPCObject. When resolving a property on a XOW as // same-origin because of UniversalXPConnect, we actually resolve it on the // UXPCObject (which is just a XOW for the same object). This causes the JS // engine to do all of its work on another object, not polluting the main // object. However, if the get results in calling a setter, the engine still // uses the regular object as 'this', ensuring that the UXPCObject doesn't // leak to script. static JSObject * GetUXPCObject(JSContext *cx, JSObject *obj) { NS_ASSERTION(STOBJ_GET_CLASS(obj) == &sXPC_XOW_JSClass.base, "wrong object"); jsval v; if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &v)) { return nsnull; } if (HAS_FLAGS(v, FLAG_IS_UXPC_OBJECT)) { return obj; } if (!JS_GetReservedSlot(cx, obj, sUXPCObjectSlot, &v)) { return nsnull; } if (JSVAL_IS_OBJECT(v)) { return JSVAL_TO_OBJECT(v); } JSObject *uxpco = JS_NewObjectWithGivenProto(cx, &sXPC_XOW_JSClass.base, nsnull, STOBJ_GET_PARENT(obj)); if (!uxpco) { return nsnull; } JSAutoTempValueRooter tvr(cx, uxpco); jsval wrappedObj, parentScope; if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sWrappedObjSlot, &wrappedObj) || !JS_GetReservedSlot(cx, obj, XPC_XOW_ScopeSlot, &parentScope)) { return nsnull; } if (!JS_SetReservedSlot(cx, uxpco, XPCWrapper::sWrappedObjSlot, wrappedObj) || !JS_SetReservedSlot(cx, uxpco, XPCWrapper::sFlagsSlot, INT_TO_JSVAL(FLAG_IS_UXPC_OBJECT)) || !JS_SetReservedSlot(cx, uxpco, XPC_XOW_ScopeSlot, parentScope)) { return nsnull; } if (!JS_SetReservedSlot(cx, obj, sUXPCObjectSlot, OBJECT_TO_JSVAL(uxpco))) { return nsnull; } return uxpco; }
static JSBool AfxGlobal_testObject(JSContext *cx, unsigned argc, JS::Value *vp) { JS::RootedObject thisobj(cx, JS_THIS_OBJECT(cx, vp)); if (!thisobj) return false; JSObject *obj = JS_NewObjectWithGivenProto(cx, &JsTestObject_class, NULL, JS_GetGlobalForScopeChain(cx)); JS_DefineProperties(cx, obj, JsTestObject_properties); JS_SetPrivate(obj, new JsTestObject()); JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj)); return JS_TRUE; }
static JSBool js_db_step(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { js_db_t *jd = JS_GetPrivate(cx, obj); if(js_db_check(cx, jd)) return JS_FALSE; if(jd->jd_stmt == NULL) { *rval = JSVAL_NULL; } else if(jd->jd_step_rc == SQLITE_ROW) { int cols = sqlite3_data_count(jd->jd_stmt); int i; JSObject *r = JS_NewObjectWithGivenProto(cx, NULL, NULL, obj); *rval = OBJECT_TO_JSVAL(r); if(!JS_EnterLocalRootScope(cx)) return JS_FALSE; for(i = 0; i < cols; i++) { const char *cn = sqlite3_column_name(jd->jd_stmt, i); switch(sqlite3_column_type(jd->jd_stmt, i)) { case SQLITE_INTEGER: js_set_prop_int(cx, r, cn, sqlite3_column_int(jd->jd_stmt, i)); break; case SQLITE_TEXT: js_set_prop_str(cx, r, cn, (const char *)sqlite3_column_text(jd->jd_stmt, i)); break; case SQLITE_FLOAT: js_set_prop_dbl(cx, r, cn, sqlite3_column_double(jd->jd_stmt, i)); break; } } JS_LeaveLocalRootScope(cx); return js_stmt_step(cx, jd, rval); } *rval = JSVAL_FALSE; return JS_TRUE; }
// static JSObject* DOMProxyHandler::EnsureExpandoObject(JSContext* cx, JS::Handle<JSObject*> obj) { NS_ASSERTION(IsDOMProxy(obj), "expected a DOM proxy object"); JS::Value v = js::GetProxyExtra(obj, JSPROXYSLOT_EXPANDO); if (v.isObject()) { return &v.toObject(); } js::ExpandoAndGeneration* expandoAndGeneration; if (!v.isUndefined()) { expandoAndGeneration = static_cast<js::ExpandoAndGeneration*>(v.toPrivate()); if (expandoAndGeneration->expando.isObject()) { return &expandoAndGeneration->expando.toObject(); } } else { expandoAndGeneration = nullptr; } JS::Rooted<JSObject*> expando(cx, JS_NewObjectWithGivenProto(cx, nullptr, nullptr, js::GetObjectParent(obj))); if (!expando) { return nullptr; } nsISupports* native = UnwrapDOMObject<nsISupports>(obj); nsWrapperCache* cache; CallQueryInterface(native, &cache); if (expandoAndGeneration) { cache->PreserveWrapper(native); expandoAndGeneration->expando.setObject(*expando); return expando; } XPCWrappedNativeScope* scope = xpc::GetObjectScope(obj); if (!scope->RegisterDOMExpandoObject(obj)) { return nullptr; } cache->SetPreservingWrapper(true); js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, ObjectValue(*expando)); return expando; }
JSBool js_db_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { const char *name; char path[URL_MAX]; char errbuf[512]; if(!JS_ConvertArguments(cx, argc, argv, "s", &name)) return JS_FALSE; js_plugin_t *jsp = JS_GetPrivate(cx, obj); snprintf(path, sizeof(path), "file://%s/plugins/%s/databases", gconf.persistent_path, jsp->jsp_id); if(fa_makedirs(path, errbuf, sizeof(errbuf))) { JS_ReportError(cx, errbuf); return JS_FALSE; } snprintf(path, sizeof(path), "%s/plugins/%s/databases/%s", gconf.persistent_path, jsp->jsp_id, name); sqlite3 *db = db_open(path, 0); if(db == NULL) { JS_ReportError(cx, "Unable to open database -- check logs"); return JS_FALSE; } JSObject *robj = JS_NewObjectWithGivenProto(cx, &db_class, NULL, obj); *rval = OBJECT_TO_JSVAL(robj); js_db_t *jd = calloc(1, sizeof(js_db_t)); jd->jd_db = db; snprintf(path, sizeof(path), "%s:%s", jsp->jsp_id, name); jd->jd_name = strdup(path); jd->jd_self = hts_thread_current(); JS_SetPrivate(cx, robj, jd); JS_DefineFunctions(cx, robj, db_functions); return JS_TRUE; }
// static JSObject* DOMProxyHandler::EnsureExpandoObject(JSContext* cx, JS::Handle<JSObject*> obj) { CheckDOMProxy(obj); JS::Value v = js::GetProxyPrivate(obj); if (v.isObject()) { CheckExpandoObject(obj, v); return &v.toObject(); } js::ExpandoAndGeneration* expandoAndGeneration; if (!v.isUndefined()) { expandoAndGeneration = static_cast<js::ExpandoAndGeneration*>(v.toPrivate()); CheckExpandoAndGeneration(obj, expandoAndGeneration); if (expandoAndGeneration->expando.isObject()) { return &expandoAndGeneration->expando.toObject(); } } else { expandoAndGeneration = nullptr; } JS::Rooted<JSObject*> expando( cx, JS_NewObjectWithGivenProto(cx, nullptr, nullptr)); if (!expando) { return nullptr; } nsISupports* native = UnwrapDOMObject<nsISupports>(obj); nsWrapperCache* cache; CallQueryInterface(native, &cache); cache->PreserveWrapper(native); if (expandoAndGeneration) { expandoAndGeneration->expando.setObject(*expando); return expando; } js::SetProxyPrivate(obj, ObjectValue(*expando)); return expando; }
JSObject* gjs_object_from_g_fundamental(JSContext *context, GIObjectInfo *info, void *gfundamental) { JSObject *proto; JSObject *object; if (gfundamental == NULL) return NULL; object = _fundamental_lookup_object(gfundamental); if (object) return object; gjs_debug_marshal(GJS_DEBUG_GFUNDAMENTAL, "Wrapping fundamental %s.%s %p with JSObject", g_base_info_get_namespace((GIBaseInfo *) info), g_base_info_get_name((GIBaseInfo *) info), gfundamental); proto = gjs_lookup_fundamental_prototype_from_gtype(context, G_TYPE_FROM_INSTANCE(gfundamental)); object = JS_NewObjectWithGivenProto(context, JS_GetClass(proto), proto, gjs_get_import_global(context)); if (object == NULL) goto out; init_fundamental_instance(context, object); associate_js_instance_to_fundamental(context, object, gfundamental, FALSE); out: return object; }
jsval CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JS::HandleObject appendParent) { JSContext* cx = m_ScriptInterface.GetContext(); JSAutoRequest rq(cx); uint8_t type; NumberU8_Unbounded("type", type); switch (type) { case SCRIPT_TYPE_VOID: return JS::UndefinedValue(); case SCRIPT_TYPE_NULL: return JS::NullValue(); case SCRIPT_TYPE_ARRAY: case SCRIPT_TYPE_OBJECT: case SCRIPT_TYPE_OBJECT_PROTOTYPE: { JS::RootedObject obj(cx); if (appendParent) { obj.set(appendParent); } else if (type == SCRIPT_TYPE_ARRAY) { u32 length; NumberU32_Unbounded("array length", length); obj.set(JS_NewArrayObject(cx, length)); } else if (type == SCRIPT_TYPE_OBJECT) { obj.set(JS_NewPlainObject(cx)); } else // SCRIPT_TYPE_OBJECT_PROTOTYPE { std::wstring prototypeName; String("proto name", prototypeName, 0, 256); // Get constructor object JS::RootedObject proto(cx); GetSerializablePrototype(prototypeName, &proto); if (!proto) throw PSERROR_Deserialize_ScriptError("Failed to find serializable prototype for object"); JS::RootedObject parent(cx, JS_GetParent(proto)); if (!proto || !parent) throw PSERROR_Deserialize_ScriptError(); // TODO: Remove support for parent since this is dropped upstream SpiderMonkey obj.set(JS_NewObjectWithGivenProto(cx, nullptr, proto, parent)); if (!obj) throw PSERROR_Deserialize_ScriptError("JS_NewObject failed"); // Does it have custom Deserialize function? // if so, we let it handle the deserialized data, rather than adding properties directly bool hasCustomDeserialize, hasCustomSerialize; if (!JS_HasProperty(cx, obj, "Serialize", &hasCustomSerialize) || !JS_HasProperty(cx, obj, "Deserialize", &hasCustomDeserialize)) throw PSERROR_Serialize_ScriptError("JS_HasProperty failed"); if (hasCustomDeserialize) { AddScriptBackref(obj); JS::RootedValue serialize(cx); if (!JS_GetProperty(cx, obj, "Serialize", &serialize)) throw PSERROR_Serialize_ScriptError("JS_GetProperty failed"); bool hasNullSerialize = hasCustomSerialize && serialize.isNull(); // If Serialize is null, we'll still call Deserialize but with undefined argument JS::RootedValue data(cx); if (!hasNullSerialize) ScriptVal("data", &data); JS::RootedValue objVal(cx, JS::ObjectValue(*obj)); m_ScriptInterface.CallFunctionVoid(objVal, "Deserialize", data); return JS::ObjectValue(*obj); } } if (!obj) throw PSERROR_Deserialize_ScriptError("Deserializer failed to create new object"); AddScriptBackref(obj); uint32_t numProps; NumberU32_Unbounded("num props", numProps); bool isLatin1; for (uint32_t i = 0; i < numProps; ++i) { Bool("isLatin1", isLatin1); if (isLatin1) { std::vector<JS::Latin1Char> propname; ReadStringLatin1("prop name", propname); JS::RootedValue propval(cx, ReadScriptVal("prop value", JS::NullPtr())); utf16string prp(propname.begin(), propname.end());; // TODO: Should ask upstream about getting a variant of JS_SetProperty with a length param. if (!JS_SetUCProperty(cx, obj, (const char16_t*)prp.data(), prp.length(), propval)) throw PSERROR_Deserialize_ScriptError(); } else { utf16string propname; ReadStringUTF16("prop name", propname); JS::RootedValue propval(cx, ReadScriptVal("prop value", JS::NullPtr())); if (!JS_SetUCProperty(cx, obj, (const char16_t*)propname.data(), propname.length(), propval)) throw PSERROR_Deserialize_ScriptError(); } } return JS::ObjectValue(*obj); } case SCRIPT_TYPE_STRING: { JS::RootedString str(cx); ScriptString("string", &str); return JS::StringValue(str); } case SCRIPT_TYPE_INT: { int32_t value; NumberI32("value", value, JSVAL_INT_MIN, JSVAL_INT_MAX); return JS::NumberValue(value); } case SCRIPT_TYPE_DOUBLE: { double value; NumberDouble_Unbounded("value", value); JS::RootedValue rval(cx, JS::NumberValue(value)); if (rval.isNull()) throw PSERROR_Deserialize_ScriptError("JS_NewNumberValue failed"); return rval; } case SCRIPT_TYPE_BOOLEAN: { uint8_t value; NumberU8("value", value, 0, 1); return JS::BooleanValue(value ? true : false); } case SCRIPT_TYPE_BACKREF: { u32 tag; NumberU32_Unbounded("tag", tag); JS::RootedObject obj(cx); GetScriptBackref(tag, &obj); if (!obj) throw PSERROR_Deserialize_ScriptError("Invalid backref tag"); return JS::ObjectValue(*obj); } case SCRIPT_TYPE_OBJECT_NUMBER: { double value; NumberDouble_Unbounded("value", value); JS::RootedValue val(cx, JS::NumberValue(value)); JS::RootedObject ctorobj(cx); if (!JS_GetClassObject(cx, JSProto_Number, &ctorobj)) throw PSERROR_Deserialize_ScriptError("JS_GetClassObject failed"); JS::RootedObject obj(cx, JS_New(cx, ctorobj, JS::HandleValueArray(val))); if (!obj) throw PSERROR_Deserialize_ScriptError("JS_New failed"); AddScriptBackref(obj); return JS::ObjectValue(*obj); } case SCRIPT_TYPE_OBJECT_STRING: { JS::RootedString str(cx); ScriptString("value", &str); if (!str) throw PSERROR_Deserialize_ScriptError(); JS::RootedValue val(cx, JS::StringValue(str)); JS::RootedObject ctorobj(cx); if (!JS_GetClassObject(cx, JSProto_String, &ctorobj)) throw PSERROR_Deserialize_ScriptError("JS_GetClassObject failed"); JS::RootedObject obj(cx, JS_New(cx, ctorobj, JS::HandleValueArray(val))); if (!obj) throw PSERROR_Deserialize_ScriptError("JS_New failed"); AddScriptBackref(obj); return JS::ObjectValue(*obj); } case SCRIPT_TYPE_OBJECT_BOOLEAN: { bool value; Bool("value", value); JS::RootedValue val(cx, JS::BooleanValue(value)); JS::RootedObject ctorobj(cx); if (!JS_GetClassObject(cx, JSProto_Boolean, &ctorobj)) throw PSERROR_Deserialize_ScriptError("JS_GetClassObject failed"); JS::RootedObject obj(cx, JS_New(cx, ctorobj, JS::HandleValueArray(val))); if (!obj) throw PSERROR_Deserialize_ScriptError("JS_New failed"); AddScriptBackref(obj); return JS::ObjectValue(*obj); } case SCRIPT_TYPE_TYPED_ARRAY: { u8 arrayType; u32 byteOffset, length; NumberU8_Unbounded("array type", arrayType); NumberU32_Unbounded("byte offset", byteOffset); NumberU32_Unbounded("length", length); // To match the serializer order, we reserve the typed array's backref tag here JS::RootedObject arrayObj(cx); AddScriptBackref(arrayObj); // Get buffer object JS::RootedValue bufferVal(cx, ReadScriptVal("buffer", JS::NullPtr())); if (!bufferVal.isObject()) throw PSERROR_Deserialize_ScriptError(); JS::RootedObject bufferObj(cx, &bufferVal.toObject()); if (!JS_IsArrayBufferObject(bufferObj)) throw PSERROR_Deserialize_ScriptError("js_IsArrayBuffer failed"); switch(arrayType) { case SCRIPT_TYPED_ARRAY_INT8: arrayObj = JS_NewInt8ArrayWithBuffer(cx, bufferObj, byteOffset, length); break; case SCRIPT_TYPED_ARRAY_UINT8: arrayObj = JS_NewUint8ArrayWithBuffer(cx, bufferObj, byteOffset, length); break; case SCRIPT_TYPED_ARRAY_INT16: arrayObj = JS_NewInt16ArrayWithBuffer(cx, bufferObj, byteOffset, length); break; case SCRIPT_TYPED_ARRAY_UINT16: arrayObj = JS_NewUint16ArrayWithBuffer(cx, bufferObj, byteOffset, length); break; case SCRIPT_TYPED_ARRAY_INT32: arrayObj = JS_NewInt32ArrayWithBuffer(cx, bufferObj, byteOffset, length); break; case SCRIPT_TYPED_ARRAY_UINT32: arrayObj = JS_NewUint32ArrayWithBuffer(cx, bufferObj, byteOffset, length); break; case SCRIPT_TYPED_ARRAY_FLOAT32: arrayObj = JS_NewFloat32ArrayWithBuffer(cx, bufferObj, byteOffset, length); break; case SCRIPT_TYPED_ARRAY_FLOAT64: arrayObj = JS_NewFloat64ArrayWithBuffer(cx, bufferObj, byteOffset, length); break; case SCRIPT_TYPED_ARRAY_UINT8_CLAMPED: arrayObj = JS_NewUint8ClampedArrayWithBuffer(cx, bufferObj, byteOffset, length); break; default: throw PSERROR_Deserialize_ScriptError("Failed to deserialize unrecognized typed array view"); } if (!arrayObj) throw PSERROR_Deserialize_ScriptError("js_CreateTypedArrayWithBuffer failed"); return JS::ObjectValue(*arrayObj); } case SCRIPT_TYPE_ARRAY_BUFFER: { u32 length; NumberU32_Unbounded("buffer length", length); #if BYTE_ORDER != LITTLE_ENDIAN #error TODO: need to convert JS ArrayBuffer data from little-endian #endif void* contents = malloc(length); ENSURE(contents); RawBytes("buffer data", (u8*)contents, length); JS::RootedObject bufferObj(cx, JS_NewArrayBufferWithContents(cx, length, contents)); AddScriptBackref(bufferObj); return JS::ObjectValue(*bufferObj); } case SCRIPT_TYPE_OBJECT_MAP: { JS::RootedObject obj(cx, JS::NewMapObject(cx)); AddScriptBackref(obj); u32 mapSize; NumberU32_Unbounded("map size", mapSize); for (u32 i=0; i<mapSize; ++i) { JS::RootedValue key(cx, ReadScriptVal("map key", JS::NullPtr())); JS::RootedValue value(cx, ReadScriptVal("map value", JS::NullPtr())); JS::MapSet(cx, obj, key, value); } return JS::ObjectValue(*obj); } case SCRIPT_TYPE_OBJECT_SET: { JS::RootedValue setVal(cx); m_ScriptInterface.Eval("(new Set())", &setVal); JS::RootedObject setObj(cx, &setVal.toObject()); AddScriptBackref(setObj); u32 setSize; NumberU32_Unbounded("set size", setSize); for (u32 i=0; i<setSize; ++i) { JS::RootedValue value(cx, ReadScriptVal("set value", JS::NullPtr())); m_ScriptInterface.CallFunctionVoid(setVal, "add", value); } return setVal; } default: throw PSERROR_Deserialize_OutOfBounds(); } }
JSBool XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp, XPCWrappedNative* wn) { NS_ASSERTION(XPCPerThreadData::IsMainThread(cx), "Can't do this off the main thread!"); // Our argument should be a wrapped native object, but the caller may have // passed it in as an optimization. JSObject *wrappedObj; if (!JSVAL_IS_OBJECT(*vp) || !(wrappedObj = JSVAL_TO_OBJECT(*vp)) || STOBJ_GET_CLASS(wrappedObj) == &sXPC_XOW_JSClass.base) { return JS_TRUE; } if (!wn && !(wn = XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, wrappedObj))) { return JS_TRUE; } XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance(); // The parent must be the inner global object for its scope. parent = JS_GetGlobalForObject(cx, parent); JSClass *clasp = STOBJ_GET_CLASS(parent); if (clasp->flags & JSCLASS_IS_EXTENDED) { JSExtendedClass *xclasp = reinterpret_cast<JSExtendedClass *>(clasp); if (xclasp->innerObject) { parent = xclasp->innerObject(cx, parent); if (!parent) { return JS_FALSE; } } } XPCWrappedNativeScope *parentScope = XPCWrappedNativeScope::FindInJSObjectScope(cx, parent, nsnull, rt); #ifdef DEBUG_mrbkap_off printf("Wrapping object at %p (%s) [%p]\n", (void *)wrappedObj, STOBJ_GET_CLASS(wrappedObj)->name, (void *)parentScope); #endif JSObject *outerObj = nsnull; WrappedNative2WrapperMap *map = parentScope->GetWrapperMap(); outerObj = map->Find(wrappedObj); if (outerObj) { NS_ASSERTION(STOBJ_GET_CLASS(outerObj) == &sXPC_XOW_JSClass.base, "What crazy object are we getting here?"); #ifdef DEBUG_mrbkap_off printf("But found a wrapper in the map %p!\n", (void *)outerObj); #endif *vp = OBJECT_TO_JSVAL(outerObj); return JS_TRUE; } outerObj = JS_NewObjectWithGivenProto(cx, &sXPC_XOW_JSClass.base, nsnull, parent); if (!outerObj) { return JS_FALSE; } if (!JS_SetReservedSlot(cx, outerObj, XPCWrapper::sWrappedObjSlot, *vp) || !JS_SetReservedSlot(cx, outerObj, XPCWrapper::sFlagsSlot, JSVAL_ZERO) || !JS_SetReservedSlot(cx, outerObj, XPC_XOW_ScopeSlot, PRIVATE_TO_JSVAL(parentScope))) { return JS_FALSE; } *vp = OBJECT_TO_JSVAL(outerObj); map->Add(wn->GetScope()->GetWrapperMap(), wrappedObj, outerObj); return JS_TRUE; }
JSBool WrapObject(JSContext *cx, JSObject *scope, jsval v, jsval *vp) { // This might be redundant if called from XPC_SJOW_Construct, but it should // be cheap in that case. JSObject *objToWrap = UnsafeUnwrapSecurityWrapper(cx, JSVAL_TO_OBJECT(v)); if (!objToWrap || JS_TypeOfValue(cx, OBJECT_TO_JSVAL(objToWrap)) == JSTYPE_XML) { return ThrowException(NS_ERROR_INVALID_ARG, cx); } // Prevent script created Script objects from ever being wrapped // with XPCSafeJSObjectWrapper, and never let the eval function // object be directly wrapped. if (objToWrap->getClass() == &js_ScriptClass || (JS_ObjectIsFunction(cx, objToWrap) && JS_GetFunctionFastNative(cx, JS_ValueToFunction(cx, v)) == XPCWrapper::sEvalNative)) { return ThrowException(NS_ERROR_INVALID_ARG, cx); } XPCWrappedNativeScope *xpcscope = XPCWrappedNativeScope::FindInJSObjectScope(cx, scope); NS_ASSERTION(xpcscope, "what crazy scope are we in?"); XPCWrappedNative *wrappedNative; WrapperType type = xpcscope->GetWrapperFor(cx, objToWrap, SJOW, &wrappedNative); // NB: We allow XOW here because we're as restrictive as it is (and we know // we're same origin here). if (type != NONE && type != XOW && !(type & SJOW)) { return ThrowException(NS_ERROR_INVALID_ARG, cx); } SLIM_LOG_WILL_MORPH(cx, objToWrap); if (IS_SLIM_WRAPPER(objToWrap) && !MorphSlimWrapper(cx, objToWrap)) { return ThrowException(NS_ERROR_FAILURE, cx); } XPCWrappedNative *wn = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, objToWrap); if (wn) { CheckWindow(wn); } JSObject *wrapperObj = JS_NewObjectWithGivenProto(cx, js::Jsvalify(&SJOWClass), nsnull, scope); if (!wrapperObj) { // JS_NewObjectWithGivenProto already threw. return JS_FALSE; } *vp = OBJECT_TO_JSVAL(wrapperObj); if (!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sWrappedObjSlot, OBJECT_TO_JSVAL(objToWrap)) || !JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sFlagsSlot, JSVAL_ZERO)) { return JS_FALSE; } return JS_TRUE; }
static JSBool js_appendItem0(JSContext *cx, js_model_t *model, prop_t *parent, const char *url, const char *type, JSObject *metaobj, jsval *data, jsval *rval, int enabled, const char *metabind) { install_nodesub(model); prop_t *item = prop_create_root(NULL); rstr_t *rurl = url ? rstr_alloc(url) : NULL; if(url != NULL) prop_set(item, "url", PROP_SET_RSTRING, rurl); if(data != NULL) js_prop_set_from_jsval(cx, prop_create(item, "data"), *data); *rval = JSVAL_VOID; if(metabind != NULL) playinfo_bind_url_to_prop(metabind, item); if(type != NULL) { prop_set_string(prop_create(item, "type"), type); if(metaobj) js_prop_from_object(cx, metaobj, prop_create(item, "metadata")); } else if(url != NULL) { if(backend_resolve_item(url, item)) { prop_destroy(item); rstr_release(rurl); return JS_TRUE; } } prop_set_int(prop_create(item, "enabled"), enabled); prop_t *p = prop_ref_inc(item); if(prop_set_parent(item, parent)) { prop_destroy(item); prop_ref_dec(p); } else { JSObject *robj = JS_NewObjectWithGivenProto(cx, &item_class, JSVAL_TO_OBJECT(model->jm_item_proto), NULL); *rval = OBJECT_TO_JSVAL(robj); js_item_t *ji = calloc(1, sizeof(js_item_t)); atomic_add(&model->jm_refcount, 1); ji->ji_url = rstr_dup(rurl); ji->ji_model = model; ji->ji_root = p; TAILQ_INSERT_TAIL(&model->jm_items, ji, ji_link); JS_SetPrivate(cx, robj, ji); ji->ji_enable_set_property = 1; ji->ji_eventsub = prop_subscribe(PROP_SUB_TRACK_DESTROY, PROP_TAG_CALLBACK, js_item_eventsub, ji, PROP_TAG_ROOT, ji->ji_root, PROP_TAG_COURIER, model->jm_pc, NULL); model->jm_subs++; ji->ji_this = OBJECT_TO_JSVAL(robj); JS_AddNamedRoot(cx, &ji->ji_this, "item_this"); prop_tag_set(ji->ji_root, model, ji); } rstr_release(rurl); return JS_TRUE; }
JSBool WrapObject(JSContext *cx, JSObject *parent, jsval *vp, XPCWrappedNative* wn) { NS_ASSERTION(XPCPerThreadData::IsMainThread(cx), "Can't do this off the main thread!"); // Our argument should be a wrapped native object, but the caller may have // passed it in as an optimization. JSObject *wrappedObj; if (JSVAL_IS_PRIMITIVE(*vp) || !(wrappedObj = JSVAL_TO_OBJECT(*vp)) || wrappedObj->getClass() == &XOWClass) { return JS_TRUE; } if (!wn && !(wn = XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, wrappedObj))) { return JS_TRUE; } CheckWindow(wn); // The parent must be the inner global object for its scope. parent = JS_GetGlobalForObject(cx, parent); OBJ_TO_INNER_OBJECT(cx, parent); if (!parent) { return JS_FALSE; } XPCWrappedNativeWithXOW *wnxow = nsnull; if (wn->NeedsXOW()) { JSObject *innerWrappedObj = wrappedObj; OBJ_TO_INNER_OBJECT(cx, innerWrappedObj); if (!innerWrappedObj) { return JS_FALSE; } if (innerWrappedObj == parent) { wnxow = static_cast<XPCWrappedNativeWithXOW *>(wn); JSObject *xow = wnxow->GetXOW(); if (xow) { *vp = OBJECT_TO_JSVAL(xow); return JS_TRUE; } } } XPCWrappedNative *parentwn = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, parent); XPCWrappedNativeScope *parentScope; if (NS_LIKELY(parentwn)) { parentScope = parentwn->GetScope(); } else { parentScope = XPCWrappedNativeScope::FindInJSObjectScope(cx, parent); } JSObject *outerObj = nsnull; WrappedNative2WrapperMap *map = parentScope->GetWrapperMap(); outerObj = map->Find(wrappedObj); if (outerObj) { NS_ASSERTION(outerObj->getClass() == &XOWClass, "What crazy object are we getting here?"); *vp = OBJECT_TO_JSVAL(outerObj); if (wnxow) { // NB: wnxow->GetXOW() must have returned false. SetFlags(cx, outerObj, AddFlags(GetFlags(cx, outerObj), FLAG_IS_CACHED)); wnxow->SetXOW(outerObj); } return JS_TRUE; } outerObj = JS_NewObjectWithGivenProto(cx, js::Jsvalify(&XOWClass), nsnull, parent); if (!outerObj) { return JS_FALSE; } jsval flags = INT_TO_JSVAL(wnxow ? FLAG_IS_CACHED : 0); if (!JS_SetReservedSlot(cx, outerObj, sWrappedObjSlot, *vp) || !JS_SetReservedSlot(cx, outerObj, sFlagsSlot, flags) || !JS_SetReservedSlot(cx, outerObj, XPC_XOW_ScopeSlot, PRIVATE_TO_JSVAL(parentScope))) { return JS_FALSE; } *vp = OBJECT_TO_JSVAL(outerObj); map->Add(wn->GetScope()->GetWrapperMap(), wrappedObj, outerObj); if(wnxow) { wnxow->SetXOW(outerObj); } return JS_TRUE; }