JSObject *GetXBLScope(JSContext *cx, JSObject *contentScope) { JSAutoCompartment ac(cx, contentScope); JSObject *scope = EnsureCompartmentPrivate(contentScope)->scope->EnsureXBLScope(cx); scope = js::UnwrapObject(scope); xpc_UnmarkGrayObject(scope); return scope; }
JSObject *GetXBLScope(JSContext *cx, JSObject *contentScope) { JSAutoCompartment ac(cx, contentScope); JSObject *scope = EnsureCompartmentPrivate(contentScope)->scope->EnsureXBLScope(cx); NS_ENSURE_TRUE(scope, nullptr); // See bug 858642. scope = js::UnwrapObject(scope); xpc_UnmarkGrayObject(scope); return scope; }
JSObject * WrapperFactory::GetXrayWaiver(JSObject *obj) { // Object should come fully unwrapped but outerized. MOZ_ASSERT(obj == UncheckedUnwrap(obj)); MOZ_ASSERT(!js::GetObjectClass(obj)->ext.outerObject); XPCWrappedNativeScope *scope = GetObjectScope(obj); MOZ_ASSERT(scope); if (!scope->mWaiverWrapperMap) return NULL; return xpc_UnmarkGrayObject(scope->mWaiverWrapperMap->Find(obj)); }
JSObject * WrapperFactory::WaiveXray(JSContext *cx, JSObject *obj) { obj = UnwrapObject(obj); // We have to make sure that if we're wrapping an outer window, that // the .wrappedJSObject also wraps the outer window. obj = GetCurrentOuter(cx, obj); { // See if we already have a waiver wrapper for this object. CompartmentPrivate *priv = (CompartmentPrivate *)JS_GetCompartmentPrivate(js::GetObjectCompartment(obj)); JSObject *wobj = nsnull; if (priv && priv->waiverWrapperMap) { wobj = priv->waiverWrapperMap->Find(obj); xpc_UnmarkGrayObject(wobj); } // No wrapper yet, make one. if (!wobj) { JSObject *proto = js::GetObjectProto(obj); if (proto && !(proto = WaiveXray(cx, proto))) return nsnull; JSAutoEnterCompartment ac; if (!ac.enter(cx, obj) || !JS_WrapObject(cx, &proto)) return nsnull; wobj = Wrapper::New(cx, obj, proto, JS_GetGlobalForObject(cx, obj), &WaiveXrayWrapperWrapper); if (!wobj) return nsnull; // Add the new wrapper so we find it next time. if (priv) { if (!priv->waiverWrapperMap) { priv->waiverWrapperMap = JSObject2JSObjectMap::newMap(XPC_WRAPPER_MAP_SIZE); if (!priv->waiverWrapperMap) return nsnull; } if (!priv->waiverWrapperMap->Add(obj, wobj)) return nsnull; } } obj = wobj; } return obj; }
JSObject * XPCWrappedNativeScope::GetPrototypeNoHelper(XPCCallContext& ccx) { // We could create this prototype in SetGlobal(), but all scopes // don't need one, so we save ourselves a bit of space if we // create these when they're needed. if (!mPrototypeNoHelper) { mPrototypeNoHelper = xpc_NewSystemInheritingJSObject(ccx, js::Jsvalify(&XPC_WN_NoHelper_Proto_JSClass), mPrototypeJSObject, false, mGlobalJSObject); NS_ASSERTION(mPrototypeNoHelper, "Failed to create prototype for wrappers w/o a helper"); } else { xpc_UnmarkGrayObject(mPrototypeNoHelper); } return mPrototypeNoHelper; }
nsresult nsJSUtils::CompileFunction(JSContext* aCx, JS::HandleObject aTarget, JS::CompileOptions& aOptions, const nsACString& aName, uint32_t aArgCount, const char** aArgArray, const nsAString& aBody, JSObject** aFunctionObject) { MOZ_ASSERT(js::GetEnterCompartmentDepth(aCx) > 0); MOZ_ASSERT_IF(aTarget, js::IsObjectInContextCompartment(aTarget, aCx)); MOZ_ASSERT_IF(aOptions.versionSet, aOptions.version != JSVERSION_UNKNOWN); mozilla::DebugOnly<nsIScriptContext*> ctx = GetScriptContextFromJSContext(aCx); MOZ_ASSERT_IF(ctx, ctx->IsContextInitialized()); // Since aTarget and aCx are same-compartment, there should be no distinction // between the object principal and the cx principal. // However, aTarget may be null in the wacky aShared case. So use the cx. JSPrincipals* p = JS_GetCompartmentPrincipals(js::GetContextCompartment(aCx)); aOptions.setPrincipals(p); // Do the junk Gecko is supposed to do before calling into JSAPI. xpc_UnmarkGrayObject(aTarget); // Compile. JSFunction* fun = JS::CompileFunction(aCx, aTarget, aOptions, PromiseFlatCString(aName).get(), aArgCount, aArgArray, PromiseFlatString(aBody).get(), aBody.Length()); if (!fun) { ReportPendingException(aCx); return NS_ERROR_FAILURE; } *aFunctionObject = JS_GetFunctionObject(fun); return NS_OK; }
nsresult nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent) { nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mTarget); if (!target || !mContext || !mHandler) return NS_ERROR_FAILURE; nsresult rv; nsCOMPtr<nsIMutableArray> iargv; bool handledScriptError = false; if (mEventName == nsGkAtoms::onerror) { nsCOMPtr<nsIPrivateDOMEvent> priv(do_QueryInterface(aEvent)); NS_ENSURE_TRUE(priv, NS_ERROR_UNEXPECTED); nsEvent *event = priv->GetInternalNSEvent(); if (event->message == NS_LOAD_ERROR && event->eventStructType == NS_SCRIPT_ERROR_EVENT) { nsScriptErrorEvent *scriptEvent = static_cast<nsScriptErrorEvent*>(event); // Create a temp argv for the error event. iargv = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; // Append the event args. nsCOMPtr<nsIWritableVariant> var(do_CreateInstance(NS_VARIANT_CONTRACTID, &rv)); NS_ENSURE_SUCCESS(rv, rv); rv = var->SetAsWString(scriptEvent->errorMsg); NS_ENSURE_SUCCESS(rv, rv); rv = iargv->AppendElement(var, false); NS_ENSURE_SUCCESS(rv, rv); // filename var = do_CreateInstance(NS_VARIANT_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = var->SetAsWString(scriptEvent->fileName); NS_ENSURE_SUCCESS(rv, rv); rv = iargv->AppendElement(var, false); NS_ENSURE_SUCCESS(rv, rv); // line number var = do_CreateInstance(NS_VARIANT_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); rv = var->SetAsUint32(scriptEvent->lineNr); NS_ENSURE_SUCCESS(rv, rv); rv = iargv->AppendElement(var, false); NS_ENSURE_SUCCESS(rv, rv); handledScriptError = true; } } if (!handledScriptError) { iargv = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; NS_ENSURE_TRUE(iargv != nsnull, NS_ERROR_OUT_OF_MEMORY); rv = iargv->AppendElement(aEvent, false); NS_ENSURE_SUCCESS(rv, rv); } // mContext is the same context which event listener manager pushes // to JS context stack. #ifdef NS_DEBUG JSContext* cx = nsnull; nsCOMPtr<nsIJSContextStack> stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1"); NS_ASSERTION(stack && NS_SUCCEEDED(stack->Peek(&cx)) && cx && GetScriptContextFromJSContext(cx) == mContext, "JSEventListener has wrong script context?"); #endif nsCOMPtr<nsIVariant> vrv; xpc_UnmarkGrayObject(mScopeObject); xpc_UnmarkGrayObject(mHandler); rv = mContext->CallEventHandler(mTarget, mScopeObject, mHandler, iargv, getter_AddRefs(vrv)); if (NS_SUCCEEDED(rv)) { PRUint16 dataType = nsIDataType::VTYPE_VOID; if (vrv) vrv->GetDataType(&dataType); if (mEventName == nsGkAtoms::onbeforeunload) { nsCOMPtr<nsIDOMBeforeUnloadEvent> beforeUnload = do_QueryInterface(aEvent); NS_ENSURE_STATE(beforeUnload); if (dataType != nsIDataType::VTYPE_VOID) { aEvent->PreventDefault(); nsAutoString text; beforeUnload->GetReturnValue(text); // Set the text in the beforeUnload event as long as it wasn't // already set (through event.returnValue, which takes // precedence over a value returned from a JS function in IE) if ((dataType == nsIDataType::VTYPE_DOMSTRING || dataType == nsIDataType::VTYPE_CHAR_STR || dataType == nsIDataType::VTYPE_WCHAR_STR || dataType == nsIDataType::VTYPE_STRING_SIZE_IS || dataType == nsIDataType::VTYPE_WSTRING_SIZE_IS || dataType == nsIDataType::VTYPE_CSTRING || dataType == nsIDataType::VTYPE_ASTRING) && text.IsEmpty()) { vrv->GetAsDOMString(text); beforeUnload->SetReturnValue(text); } } } else if (dataType == nsIDataType::VTYPE_BOOL) { // If the handler returned false and its sense is not reversed, // or the handler returned true and its sense is reversed from // the usual (false means cancel), then prevent default. bool brv; if (NS_SUCCEEDED(vrv->GetAsBool(&brv)) && brv == (mEventName == nsGkAtoms::onerror || mEventName == nsGkAtoms::onmouseover)) { aEvent->PreventDefault(); } } } return rv; }
nsresult nsJSUtils::EvaluateString(JSContext* aCx, const nsAString& aScript, JS::Handle<JSObject*> aScopeObject, JS::CompileOptions& aCompileOptions, EvaluateOptions& aEvaluateOptions, JS::Value* aRetValue) { PROFILER_LABEL("JS", "EvaluateString"); MOZ_ASSERT_IF(aCompileOptions.versionSet, aCompileOptions.version != JSVERSION_UNKNOWN); MOZ_ASSERT_IF(aEvaluateOptions.coerceToString, aRetValue); MOZ_ASSERT_IF(!aEvaluateOptions.reportUncaught, aRetValue); MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext()); // Unfortunately, the JS engine actually compiles scripts with a return value // in a different, less efficient way. Furthermore, it can't JIT them in many // cases. So we need to be explicitly told whether the caller cares about the // return value. Callers use null to indicate they don't care. if (aRetValue) { *aRetValue = JSVAL_VOID; } xpc_UnmarkGrayObject(aScopeObject); nsAutoMicroTask mt; JSPrincipals* p = JS_GetCompartmentPrincipals(js::GetObjectCompartment(aScopeObject)); aCompileOptions.setPrincipals(p); bool ok = false; nsresult rv = nsContentUtils::GetSecurityManager()-> CanExecuteScripts(aCx, nsJSPrincipals::get(p), &ok); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(ok, NS_OK); // Scope the JSAutoCompartment so that we can later wrap the return value // into the caller's cx. { JSAutoCompartment ac(aCx, aScopeObject); JS::RootedObject rootedScope(aCx, aScopeObject); ok = JS::Evaluate(aCx, rootedScope, aCompileOptions, PromiseFlatString(aScript).get(), aScript.Length(), aRetValue); if (ok && aEvaluateOptions.coerceToString && !aRetValue->isUndefined()) { JSString* str = JS_ValueToString(aCx, *aRetValue); ok = !!str; *aRetValue = ok ? JS::StringValue(str) : JS::UndefinedValue(); } } if (!ok) { if (aEvaluateOptions.reportUncaught) { ReportPendingException(aCx); if (aRetValue) { *aRetValue = JS::UndefinedValue(); } } else { rv = JS_IsExceptionPending(aCx) ? NS_ERROR_FAILURE : NS_ERROR_OUT_OF_MEMORY; JS_GetPendingException(aCx, aRetValue); JS_ClearPendingException(aCx); } } // Wrap the return value into whatever compartment aCx was in. if (aRetValue && !JS_WrapValue(aCx, aRetValue)) return NS_ERROR_OUT_OF_MEMORY; return rv; }