nsresult abpListener::HandleEvent(nsIDOMEvent* event) { nsresult rv; abpJSContextHolder holder; JSObject* overlay = UnwrapJSObject(fakeBrowserWindow); JSContext* cx = holder.get(); if (cx == nsnull || overlay == nsnull) return NS_ERROR_FAILURE; nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID()); if (xpc == nsnull) return NS_ERROR_FAILURE; nsCOMPtr<nsIXPConnectJSObjectHolder> wrapperHolder; rv = xpc->WrapNative(cx, JS_GetParent(cx, overlay), event, NS_GET_IID(nsIDOMEvent), getter_AddRefs(wrapperHolder)); if (NS_FAILED(rv)) return rv; JSObject* jsObj; rv = wrapperHolder->GetJSObject(&jsObj); if (NS_FAILED(rv)) return rv; jsval arg = OBJECT_TO_JSVAL(jsObj); jsval retval; JS_CallFunctionName(cx, overlay, "onEvent", 1, &arg, &retval); return NS_OK; }
NS_IMETHODIMP nsJetpack::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, jsval id, PRUint32 flags, JSObject * *objp, PRBool *_retval) { if (JSVAL_IS_STRING(id) && strncmp(JS_GetStringBytes(JSVAL_TO_STRING(id)), "get", 3) == 0) { JSFunction *get = JS_NewFunction(cx, getEndpoint, 0, 0, JS_GetParent(cx, obj), "get"); if (!get) { JS_ReportOutOfMemory(cx); *_retval = PR_FALSE; return NS_OK; } JSObject *getObj = JS_GetFunctionObject(get); jsid idid; *objp = obj; *_retval = (JS_ValueToId(cx, id, &idid) && JS_DefinePropertyById(cx, obj, idid, OBJECT_TO_JSVAL(getObj), nsnull, nsnull, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)); return NS_OK; } *objp = nsnull; *_retval = PR_TRUE; return NS_OK; }
/* @location_class.setProperty */ static JSBool location_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) { JSObject *parent_win; /* instance of @window_class */ struct view_state *vs; struct document_view *doc_view; /* This can be called if @obj if not itself an instance of the * appropriate class but has one in its prototype chain. Fail * such calls. */ if (!JS_InstanceOf(ctx, obj, (JSClass *) &location_class, NULL)) return JS_FALSE; parent_win = JS_GetParent(ctx, obj); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); if_assert_failed return JS_FALSE; vs = (struct view_state *)JS_GetInstancePrivate(ctx, parent_win, (JSClass *) &window_class, NULL); doc_view = vs->doc_view; if (!JSID_IS_INT(id)) return JS_TRUE; switch (JSID_TO_INT(id)) { case JSP_LOC_HREF: location_goto(doc_view, jsval_to_string(ctx, vp)); break; } return JS_TRUE; }
static JSBool makeCOW(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { JSObject *object; if (!JS_ConvertArguments(cx, argc, argv, "o", &object)) return JS_FALSE; nsresult rv = NS_OK; nsCOMPtr<nsIXPConnect> xpc = do_GetService( "@mozilla.org/js/xpc/XPConnect;1", &rv ); if (NS_FAILED(rv)) { JS_ReportError(cx, "getting XPConnect failed"); return JS_FALSE; } rv = xpc->GetCOWForObject(cx, JS_GetParent(cx, object), object, rval); if (NS_FAILED(rv)) { JS_ReportError(cx, "nsIXPConnect->GetCOWForObject() failed"); return JS_FALSE; } return JS_TRUE; }
jsval ScriptInterface::NewObjectFromConstructor(jsval ctor) { // Get the constructor's prototype // (Can't use JS_GetPrototype, since we want .prototype not .__proto__) jsval protoVal; if (!JS_GetProperty(m->m_cx, JSVAL_TO_OBJECT(ctor), "prototype", &protoVal)) { LOGERROR(L"NewObjectFromConstructor: can't get prototype"); return JSVAL_VOID; } if (!JSVAL_IS_OBJECT(protoVal)) { LOGERROR(L"NewObjectFromConstructor: prototype is not an object"); return JSVAL_VOID; } JSObject* proto = JSVAL_TO_OBJECT(protoVal); JSObject* parent = JS_GetParent(m->m_cx, JSVAL_TO_OBJECT(ctor)); // TODO: rooting? if (!proto || !parent) { LOGERROR(L"NewObjectFromConstructor: null proto/parent"); return JSVAL_VOID; } JSObject* obj = JS_NewObject(m->m_cx, NULL, proto, parent); if (!obj) { LOGERROR(L"NewObjectFromConstructor: object creation failed"); return JSVAL_VOID; } return OBJECT_TO_JSVAL(obj); }
/* [implicit_jscontext] jsval searchScope (in jsval scope, in AString name); */ NS_IMETHODIMP dpoCInterface::SearchScope(const jsval & scope, const nsAString & name, JSContext *cx, jsval *_retval) { JSObject *scopeObj, *parentObj; JSBool result; char *propName; if (!JSVAL_IS_OBJECT(scope)) { *_retval = JSVAL_VOID; return NS_ERROR_ILLEGAL_VALUE; } scopeObj = JSVAL_TO_OBJECT(scope); parentObj = JS_GetParent(cx, scopeObj); if (parentObj == NULL) { *_retval = JSVAL_VOID; return NS_ERROR_NOT_AVAILABLE; } *_retval = OBJECT_TO_JSVAL(parentObj); return NS_OK; propName = ToNewUTF8String(name); result = JS_LookupPropertyWithFlags(cx, parentObj, propName, 0, _retval); nsMemory::Free(propName); if (result == JS_FALSE) { *_retval = JSVAL_VOID; return NS_ERROR_NOT_AVAILABLE; } return NS_OK; }
JSDValue* jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval) { JSCrossCompartmentCall *call = NULL; if(!(CHECK_BIT_FLAG(jsdval->flags, GOT_PARENT))) { JSObject* obj; JSObject* parent; JS_ASSERT(!jsdval->parent); SET_BIT_FLAG(jsdval->flags, GOT_PARENT); if(!JSVAL_IS_OBJECT(jsdval->val)) return NULL; if(!(obj = JSVAL_TO_OBJECT(jsdval->val))) return NULL; JS_BeginRequest(jsdc->dumbContext); call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj); if(!call) { JS_EndRequest(jsdc->dumbContext); return NULL; } parent = JS_GetParent(jsdc->dumbContext,obj); JS_LeaveCrossCompartmentCall(call); JS_EndRequest(jsdc->dumbContext); if(!parent) return NULL; jsdval->parent = jsd_NewValue(jsdc, OBJECT_TO_JSVAL(parent)); } if(jsdval->parent) jsdval->parent->nref++; return jsdval->parent; }
void gjs_explain_scope(JSContext *context, const char *title) { JSContext *load_context; JSContext *call_context; JSObject *global; JSObject *parent; GString *chain; gjs_debug(GJS_DEBUG_SCOPE, "=== %s ===", title); load_context = gjs_runtime_peek_load_context(JS_GetRuntime(context)); call_context = gjs_runtime_peek_call_context(JS_GetRuntime(context)); JS_BeginRequest(context); JS_BeginRequest(load_context); JS_BeginRequest(call_context); JS_EnterLocalRootScope(context); gjs_debug(GJS_DEBUG_SCOPE, " Context: %p %s", context, context == load_context ? "(LOAD CONTEXT)" : context == call_context ? "(CALL CONTEXT)" : ""); global = JS_GetGlobalObject(context); gjs_debug(GJS_DEBUG_SCOPE, " Global: %p %s", global, gjs_value_debug_string(context, OBJECT_TO_JSVAL(global))); parent = JS_GetScopeChain(context); chain = g_string_new(NULL); while (parent != NULL) { const char *debug; debug = gjs_value_debug_string(context, OBJECT_TO_JSVAL(parent)); if (chain->len > 0) g_string_append(chain, ", "); g_string_append_printf(chain, "%p %s", parent, debug); parent = JS_GetParent(context, parent); } gjs_debug(GJS_DEBUG_SCOPE, " Chain: %s", chain->str); g_string_free(chain, TRUE); JS_LeaveLocalRootScope(context); JS_EndRequest(call_context); JS_EndRequest(load_context); JS_EndRequest(context); }
static JSObject * define_JavaPackage(JSContext *cx, JSObject *parent_obj, const char *obj_name, const char *path, int flags, int access) { JSObject *package_obj, *obj; JavaPackage_Private *package; jsval v; /* * Expose the same JSObject for Packages.java and java. * "java" will be defined during the java package initialization stage. * "Packages.java" will be lazily resolved by JavaPackage_resolve. * Ditto for sun and netscape. * See bugzilla bug: https://bugzilla.mozilla.org/show_bug.cgi?id=248409. */ if (!strcmp(obj_name, path) && (obj = JS_GetParent(cx, parent_obj)) && JS_LookupProperty(cx, obj, obj_name, &v) && !JSVAL_IS_PRIMITIVE(v)) { if (!JS_DefineProperty(cx, parent_obj, obj_name, v, NULL, NULL, JSPROP_PERMANENT | access)) { return NULL; } package_obj = JSVAL_TO_OBJECT(v); return package_obj; } package_obj = JS_DefineObject(cx, parent_obj, obj_name, &JavaPackage_class, 0, JSPROP_PERMANENT | access); if (!package_obj) return NULL; /* Attach private, native data to the JS object */ package = (JavaPackage_Private *)JS_malloc(cx, sizeof(JavaPackage_Private)); if (!package) { JS_DeleteProperty(cx, parent_obj, obj_name); return NULL; } JS_SetPrivate(cx, package_obj, (void *)package); if (path) package->path = JS_strdup(cx, path); else package->path = ""; package->flags = flags; /* Check for OOM */ if (!package->path) { JS_DeleteProperty(cx, parent_obj, obj_name); JS_free(cx, package); return NULL; } return package_obj; }
static JSBool js_get_parent(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { JSObject* child=NULL; JSObject* parent; if(JS_ValueToObject(cx, argv[0], &child) && child!=NULL && (parent=JS_GetParent(cx,child))!=NULL) *rval = OBJECT_TO_JSVAL(parent); return(JS_TRUE); }
static JSBool js_get_parent(JSContext *cx, uintN argc, jsval *arglist) { jsval *argv=JS_ARGV(cx, arglist); JSObject* child=NULL; JSObject* parent; if(JS_ValueToObject(cx, argv[0], &child) && child!=NULL && (parent=JS_GetParent(cx,child))!=NULL) JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(parent)); return(JS_TRUE); }
static JSBool perlsub_construct( JSContext *cx, DEFJSFSARGS_ ) { dTHX; DECJSFSARGS; JSObject *func = JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv)); SV *callee = (SV *)JS_GetPrivate(cx, func); SV *caller = NULL; #if JS_VERSION < 185 JSObject *This = JSVAL_TO_OBJECT(argv[-1]); #else JSObject *This = JS_NewObjectForConstructor(cx, vp); #endif JSObject *proto = JS_GetPrototype(cx, This); PJS_DEBUG1("Want construct, This is a %s", PJS_GET_CLASS(cx, This)->name); if(PJS_GET_CLASS(cx, proto) == &perlpackage_class || ( JS_LookupProperty(cx, func, "prototype", &argv[-1]) && JSVAL_IS_OBJECT(argv[-1]) && !JSVAL_IS_NULL(argv[-1]) && (proto = JS_GetPrototype(cx, JSVAL_TO_OBJECT(argv[-1]))) && strEQ(PJS_GET_CLASS(cx, proto)->name, PJS_PACKAGE_CLASS_NAME)) ) { SV *rsv = NULL; char *pkgname = PJS_GetPackageName(aTHX_ cx, proto); #if JS_VERSION >= 185 JSAutoByteString bytes; bytes.initBytes(pkgname); #endif caller = newSVpv(pkgname, 0); argv[-1] = OBJECT_TO_JSVAL(This); if(!PJS_Call_sv_with_jsvals_rsv(aTHX_ cx, obj, callee, caller, argc, argv, &rsv, G_SCALAR)) return JS_FALSE; if(SvROK(rsv) && sv_derived_from(rsv, pkgname)) { JSObject *newobj = PJS_NewPerlObject(aTHX_ cx, JS_GetParent(cx, func), rsv); *rval = OBJECT_TO_JSVAL(newobj); return JS_TRUE; } JS_ReportError(cx, "%s's constructor don't return an object", SvPV_nolen(caller)); } else JS_ReportError(cx, "Can't use as a constructor"); // Yet! ;-) return JS_FALSE; }
// GetJSShGlobal: helper for native js functions to obtain the global // JSSh object PRBool GetJSShGlobal(JSContext *cx, JSObject *obj, nsJSSh** shell) { JSAutoRequest ar(cx); #ifdef DEBUG // printf("GetJSShGlobal(cx=%p, obj=%p)\n", cx, obj); #endif JSObject *parent, *global = obj; if (!global) { NS_ERROR("need a non-null obj to find script global"); return PR_FALSE; } // in most of our cases, 'global' is already the correct obj, since // we use bound methods. For cases where we call // GetJSShGlobal from an unbound method, we need to walk the // parent chain: // XXX I think the comment above is obsolete. We only call // GetJSShGlobal from bound methods, in which case the // parent is the global obj. For non-bound methods, walking the // parent chain to obtain the global object will only work when the // method is rooted in the current script context, so it is not // reliable (???). ASSERTION below to test the assumption. Once proven, // remove loop. while ((parent = JS_GetParent(cx, global))) { NS_ERROR("Parent chain weirdness. Probably benign, but we should not reach this."); #ifdef DEBUG // printf(" obj's parent = %p\n", parent); #endif global = parent; } // JSClass* clazz = JS_GET_CLASS(cx, global); // if (!IS_WRAPPER_CLASS(clazz)) { // NS_ERROR("the script global's class is not of the right type"); // return PR_FALSE; // } // XXX use GetWrappedNativeOfJSObject nsIXPConnectWrappedNative *wrapper = static_cast<nsIXPConnectWrappedNative*>(JS_GetPrivate(cx, global)); nsCOMPtr<nsISupports> native; wrapper->GetNative(getter_AddRefs(native)); nsCOMPtr<nsIJSSh> jssh = do_QueryInterface(native); NS_ASSERTION(jssh, "no jssh global"); *shell = static_cast<nsJSSh*>((nsIJSSh*)(jssh.get())); return PR_TRUE; }
static void passport_finalize( JSContext *cx, JSObject *passport ) { dTHX; SV *box = (SV *)JS_GetPrivate(cx, passport); if(box && SvOK(box) && SvROK(box)) { AV *avbox = (AV *)SvRV(box); #ifdef PJSDEBUG JSObject *parent = JS_GetParent(cx, passport); #endif PJS_DEBUG3("About to free a %s rc:%d,%d\n", JS_GET_CLASS(cx, parent)->name, SvREFCNT(box), SvREFCNT(avbox)); if(PL_dirty) return; av_store(avbox, 0, &PL_sv_undef); sv_free(box); } else croak("PJS_Assert: Bad finalize for passport\n"); /* Assertion */ }
JSBool js_cocos2dx_CCNode_copy(JSContext *cx, uint32_t argc, jsval *vp) { if (argc == 0) { JSObject *obj = JS_THIS_OBJECT(cx, vp); js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); cocos2d::CCNode *node = (cocos2d::CCNode *)(proxy ? proxy->ptr : NULL); TEST_NATIVE_OBJECT(cx, node) JSClass *jsclass = JS_GetClass(obj); JSObject *proto = JS_GetPrototype(obj); JSObject *parent = JS_GetParent(obj); JSObject *jsret = JS_NewObject(cx, jsclass, proto, parent); cocos2d::CCObject *ret = node->copy(); if (ret && jsret) { JS_NEW_PROXY(proxy, ret, jsret); JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(jsret)); return JS_TRUE; } } return JS_FALSE; }
/* @location_class.getProperty */ static JSBool location_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) { JSObject *parent_win; /* instance of @window_class */ struct view_state *vs; /* This can be called if @obj if not itself an instance of the * appropriate class but has one in its prototype chain. Fail * such calls. */ if (!JS_InstanceOf(ctx, obj, (JSClass *) &location_class, NULL)) return JS_FALSE; parent_win = JS_GetParent(ctx, obj); assert(JS_InstanceOf(ctx, parent_win, (JSClass *) &window_class, NULL)); if_assert_failed return JS_FALSE; vs = (struct view_state *)JS_GetInstancePrivate(ctx, parent_win, (JSClass *) &window_class, NULL); if (!JSID_IS_INT(id)) return JS_TRUE; undef_to_jsval(ctx, vp); switch (JSID_TO_INT(id)) { case JSP_LOC_HREF: astring_to_jsval(ctx, vp, get_uri_string(vs->uri, URI_ORIGINAL)); break; default: /* Unrecognized integer property ID; someone is using * the object as an array. SMJS builtin classes (e.g. * js_RegExpClass) just return JS_TRUE in this case * and leave *@vp unchanged. Do the same here. * (Actually not quite the same, as we already used * @undef_to_jsval.) */ break; } return JS_TRUE; }
PRBool Load() { nsresult rv; kFuncs = kPlugin.kFuncs; abpJSContextHolder contextHolder; JSContext* cx = contextHolder.get(); if (cx == nsnull) return PR_FALSE; nsCOMPtr<nsIScriptSecurityManager> secman = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); if (secman == nsnull) { JS_ReportError(cx, "Adblock Plus: Failed to retrieve security manager - wrong Gecko version?"); return PR_FALSE; } nsCOMPtr<nsIPrincipal> systemPrincipal; rv = secman->GetSystemPrincipal(getter_AddRefs(systemPrincipal)); if (NS_FAILED(rv) || systemPrincipal == nsnull) { JS_ReportError(cx, "Adblock Plus: Failed to retrieve system's security principal"); return PR_FALSE; } JSObject* jsObject = GetComponentObject(cx); if (jsObject == nsnull) return PR_FALSE; if (!CreateFakeBrowserWindow(cx, JS_GetParent(cx, jsObject), systemPrincipal)) return PR_FALSE; cmdBase = kFuncs->GetCommandIDs(NUM_COMMANDS); toolbarList.init(cmdBase + CMD_TOOLBAR); statusbarList.init(hImages, cmdBase + CMD_STATUSBAR, kFuncs->AddStatusBarIcon, kFuncs->RemoveStatusBarIcon); return PR_TRUE; }
static JSBool location_set_property_href(JSContext *ctx, JSHandleObject hobj, JSHandleId hid, JSBool strict, JSMutableHandleValue hvp) { ELINKS_CAST_PROP_PARAMS JSObject *parent_win; /* instance of @window_class */ struct view_state *vs; struct document_view *doc_view; /* This can be called if @obj if not itself an instance of the * appropriate class but has one in its prototype chain. Fail * such calls. */ if (!JS_InstanceOf(ctx, obj, &location_class, NULL)) return JS_FALSE; parent_win = JS_GetParent(obj); assert(JS_InstanceOf(ctx, parent_win, &window_class, NULL)); if_assert_failed return JS_FALSE; vs = JS_GetInstancePrivate(ctx, parent_win, &window_class, NULL); doc_view = vs->doc_view; location_goto(doc_view, jsval_to_string(ctx, vp)); return JS_TRUE; }
nsIScriptGlobalObject * nsWWJSUtils::GetStaticScriptGlobal(JSContext* aContext, JSObject* aObj) { nsISupports* supports; JSClass* clazz; JSObject* parent; JSObject* glob = aObj; // starting point for search if (!glob) return nsnull; while (nsnull != (parent = JS_GetParent(aContext, glob))) glob = parent; #ifdef JS_THREADSAFE clazz = JS_GetClass(aContext, glob); #else clazz = JS_GetClass(glob); #endif if (!clazz || !(clazz->flags & JSCLASS_HAS_PRIVATE) || !(clazz->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) || !(supports = (nsISupports*) JS_GetPrivate(aContext, glob))) { return nsnull; } nsCOMPtr<nsIXPConnectWrappedNative> wrapper(do_QueryInterface(supports)); NS_ENSURE_TRUE(wrapper, nsnull); nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper)); // This will return a pointer to something we're about to release, // but that's ok here. return sgo; }
static JSBool js_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { jsint tiny; js_branch_t* branch; if((branch=(js_branch_t*)JS_GetPrivate(cx,obj))==NULL) return(JS_FALSE); tiny = JSVAL_TO_INT(id); switch(tiny) { case PROP_VERSION: *vp=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,(char *)JS_GetImplementationVersion())); break; case PROP_TERMINATED: if(branch->terminated==NULL) *vp=JSVAL_FALSE; else *vp=BOOLEAN_TO_JSVAL(*branch->terminated); break; case PROP_AUTO_TERMINATE: *vp=BOOLEAN_TO_JSVAL(branch->auto_terminate); break; case PROP_BRANCH_COUNTER: JS_NewNumberValue(cx,branch->counter,vp); break; case PROP_BRANCH_LIMIT: JS_NewNumberValue(cx,branch->limit,vp); break; case PROP_YIELD_INTERVAL: JS_NewNumberValue(cx,branch->yield_interval,vp); break; case PROP_GC_INTERVAL: JS_NewNumberValue(cx,branch->gc_interval,vp); break; case PROP_GC_ATTEMPTS: JS_NewNumberValue(cx,branch->gc_attempts,vp); break; #ifdef jscntxt_h___ case PROP_GC_COUNTER: JS_NewNumberValue(cx,cx->runtime->gcNumber,vp); break; case PROP_GC_LASTBYTES: JS_NewNumberValue(cx,cx->runtime->gcLastBytes,vp); break; case PROP_BYTES: JS_NewNumberValue(cx,cx->runtime->gcBytes,vp); break; case PROP_MAXBYTES: JS_NewNumberValue(cx,cx->runtime->gcMaxBytes,vp); break; case PROP_GLOBAL: *vp = OBJECT_TO_JSVAL(cx->globalObject); break; #else case PROP_GLOBAL: *vp = OBJECT_TO_JSVAL(JS_GetParent(cx,obj)); break; #endif } return(JS_TRUE); }
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(); } }
AutoPushJSContext::AutoPushJSContext(nsISupports* aSecuritySupports, JSContext *cx) : mContext(cx), mPushResult(NS_OK) { nsCOMPtr<nsIJSContextStack> contextStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1"); JS_BeginRequest(cx); JSContext* currentCX; if(contextStack && // Don't push if the current context is already on the stack. (NS_FAILED(contextStack->Peek(¤tCX)) || cx != currentCX) ) { if (NS_SUCCEEDED(contextStack->Push(cx))) { // Leave the reference in mContextStack to // indicate that we need to pop it in our dtor. mContextStack.swap(contextStack); } } nsCOMPtr<nsIScriptSecurityManager> secMan( do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &mPushResult)); if (NS_FAILED(mPushResult)) return; nsCOMPtr<nsIPrincipal> principal; mPushResult = secMan->GetPrincipalFromContext(cx, getter_AddRefs(principal)); if (NS_FAILED(mPushResult)) { JS_ReportError(cx, "failed to get a principal"); return; } // See if JavaScript is enabled for the current window PRBool jsEnabled = PR_FALSE; mPushResult = secMan->CanExecuteScripts(cx, principal, &jsEnabled); if (!jsEnabled) mPushResult = NS_ERROR_FAILURE; memset(&mFrame, 0, sizeof(mFrame)); if (NS_SUCCEEDED(mPushResult)) { // See if there are any scripts on the stack. // If not, we need to add a dummy frame with a principal. PRBool hasScript = PR_FALSE; JSStackFrame* tempFP = cx->fp; while (tempFP) { if (tempFP->script) { hasScript = PR_TRUE; break; } tempFP = tempFP->down; }; if (!hasScript) { JSPrincipals* jsprinc; principal->GetJSPrincipals(cx, &jsprinc); JSFunction *fun = JS_CompileFunctionForPrincipals(cx, JS_GetGlobalObject(cx), jsprinc, "anonymous", 0, nsnull, "", 0, "", 1); JSPRINCIPALS_DROP(cx, jsprinc); if (fun) { JSScript *script = JS_GetFunctionScript(cx, fun); mFrame.fun = fun; mFrame.script = script; mFrame.callee = JS_GetFunctionObject(fun); mFrame.scopeChain = JS_GetParent(cx, mFrame.callee); mFrame.down = cx->fp; mRegs.pc = script->code + script->length - 1; JS_ASSERT(static_cast<JSOp>(*mRegs.pc) == JSOP_STOP); mRegs.sp = NULL; mFrame.regs = &mRegs; cx->fp = &mFrame; } else mPushResult = NS_ERROR_OUT_OF_MEMORY; } } }