Files
palemoon27/dom/bindings/CallbackObject.cpp
T
roytam1 869fcffa1f import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1262453: IonMonkey - Don't add resume point for constants, r=nbp (b5f8021cf8)
- Bug 1240521 - IonBuilder processSwitchEnd returns ControlStatus_Error on allocation errors. r=h4writer (997738a608)
- Bug 1261361 - Make Vector::infallibleGrowByUninitialized check mReserved instead of mCapacity. r=Waldo (1326f9121f)
- Bug 1254203 - SnapshotIterator::maybeRead use AutoEnterOOMUnsafeRegion instead of MOZ_CRASH. r=jandem (54fa438206)
- Bug 1261324 - Fix bogus return address for star generators' .throw being observed by the profiler in Debugger's onExceptionUnwind in Baseline. (r=jandem) (6e998a7d64)
- Bug 1263899 - Fix readFrameArgsAndLocals to always use maybeRead since it can't recover instructions. (r=nbp) (59288f533b)
- Bug 1265748 - Enable non-Object path in IonBuilder::inlineIsCallable. r=shu (c0de95d84f)
- Bug 1186006 - Assert that all blocks have an entry resume point, excepts for unreachable one added by the Value Numbering. r=sunfish (32e9a56e59)
- Bug 1257089 - Weaken the assertions to account for unreachable annotation added by Range Analysis. r=sunfish (87caf2580a)
- Bug 1263888 - Push TypeBarrier after ArraySlice. r=jandem (28e089137b)
- Bug 1246552 - IonMonkey: Don't eliminate toString on objects and symbols, r=jandem (da7c99d316)
- Bug 1258632 - Distinguish signed/unsigned MDiv/MMod in GVN. r=bbouvier (22dbf55c27)
- Bug 1263532 - Do not make RegExpPrototypeOptimizable and RegExpInstanceOptimizable movable. r=h4writer (9b4c75397f)
- Bug 1248202 - Handle an OOM case in optimization tracking. r=jandem (045d4c002c)
- Bug 1257929 - Special case OSR block to avoid bloating safeInsertTop condition. r=h4writer (738c4abd63)
- Bug 1239075 - RangeAnalysis: Assume that all captured results are used in bailing branches. r=h4writer (a8d6b4b29d)
- Bug 1256702 - Skip the operand of MAssertRecoveredOnBailout encoded in the snapshot. r=h4writer (a4705253af)
- Bug 1263895 - IonMonkey: Check return value of all functions in GVN, r=jandem (351ba8d825)
- Bug 1262453 - IonMonkey: Remove Nops which try to decrease liveness of instructions, but fail, r=bhackett (5f7e221a7a)
- Bug 1124397 - More crash diagnostics. r=nbp (4abe9de4f3)
- Bug 1124397 - Temporary diagnostic patch to help figure out what's going on. r=efaust a=kwierso (d7416f77c4)
- Bug 1124397 - Add more crash diagnostics. r=efaust (130cd14bff)
- Bug 1252326 - Reorder MacroAssembler flush functions to follow the header order. r=bbouvier (c361f37707)
- Quick follow-up to bug 1251225 to fix a possibly overflowing left shift (found by Coverity, rs=h4writer on irc) (7b33f428a5)
- Bug 1256588 - IonMonkey: MIPS64: Don't skip nops on Loongson by runtime flag. r=huangwenjun06 (7aa8d6b5d9)
- Bug 1265601 - OdinMonkey: MIPS: Fix i64 testing infrastructure in Baldr. r=bbouvier (f5dfa86b4d)
- Bug 1263090 - OdinMonkey: MIPS: Implement AsmReinterpretFromI64/ToI64. r=bbouvier (3c0bed4a24)
- Bug 1263094 - IonMonkey: MIPS: Change members to non-virtual in CodeGenerator. r=arai (195bfaa03f)
- Bug 1258253 - IonMonkey: MIPS64: Fix MacroAssembler::branchTestMagic. r=arai (6420433ec0)
- Bug 1258253 - IonMonkey: MIPS64: Fix MacroAssembler::branchValueIsNurseryObject. r=arai (271089e08e)
- Bug 1249895 - Replace unsigned __int128_t with __uint128_t. r=hev (8d29fb5234)
- Bug 1258907 - IonMonkey: MIPS32: Fix MacroAssembler::branchValueIsNurseryObject. r=arai (18ae03452f)
- Bug 1256588 - IonMonkey: MIPS: Implement isLoongson. r=huangwenjun06 (d82314788d)
- Bug 1260694 - IonMonkey: MIPS: Inline get MIPS flags. r=huangwenjun06 (caf060f2ed)
- Bug 1258277 - OdinMonkey: MIPS: Leave ARCH_BITS for CPUID. r=huangwenjun06 (8d2ce72d21)
- Bug 1263090 - OdinMonkey: MIPS: Implement AsmReinterpret. r=bbouvier (d1a98954e1)
- Bug 1258293 - IonMonkey: MIPS: Refactor float-point Not by conditional move. r=arai (269c5d3be9)
- Bug 1254369 - IonMonkey: MIPS: Clean up broken assertions. r=arai (aedad3d82a)
- Bug 1254369 - IonMonkey: MIPS: Fix header files missing in MacroAssembler. r=arai (c8b291d450)
- Bug 1250370 - IonMonkey: MIPS: Fix stack alignment checking in EmitBaselineEnterStubFrame. r=nbp (77cd114731)
- Bug 1247312 - Don't generate invalid LDRD instructions on ARM. r=nbp (440e999cf7)
- Bug 1258999: Check for OOM after flushing pools when merging MacroAssemblers; r=efaust (ad22c913ff)
- Bug 1234408 - Fix ARM assembler to bind labels on OOM to silence ~Label assert. r=bbouvier (a4b3f716b1)
- Bug 1254106 - IonMonkey: Disable assertion of incorrect labels on OOM on ARM, like on x86 and x64, r=jandem (86b143ff42)
- cleanup (1a71c7a761)
- Bug 1263040 - Add Intl.getCanonicalLocales. r=jwalden (999911b0b3)
- Bug 1259540 - Fix missing header include that breaks FILES_PER_UNIFIED_FILE=1. r=till (247f599cd9)
- Bug 1263118 - Fix replace substitution without any capture. r=till (c6d500b683)
- Bug 1265449: Remove static assumption about SIMD objects; r=jonco (cfe92c4636)
- Bug 1259600 - Divert typed arrays passed to Array.sort to a typed array specific sort; r=till (f91e07bb1b)
- Bug 1260673 - Stop using _DefineDataProperty in MoveHoles; r=jorendorff (e476f59b01)
- Bug 1260673 - Ensure that Array.sort works with sealed objects; r=jorendorff (6aba58306d)
- Bug 1261813: Ensure the argument to wasmBinaryToText always has a buffer; r=luke (7c86782427)
- Bug 1204562 - GetMethod should not box the receiver argument. r=till (8977188519)
- Bug 552533 - Support thiscall Win32 ABI for js-ctypes. Original patch is dwitte. r=jorendorff (3179fe82fb)
- Bug 1252958 - Implement Debugger.adoptDebuggeeValue;r=jimb (bb1eed3603)
- Bug 1261904 - Refactor Debugger.Object.getErrorMessageName; r=jimb (414b03ce1a)
- Bug 1256560 - Implement AnimationEffectTiming WebIDL. r=birtles, r=smaug (123bc00be6)
- Bug 1244643 - Part 1: Implement AnimationEffectTiming easing. r=hiro (958cde39eb)
- Bug 1244640 - implement AnimationEffectTiming iterations r=hiro (30420e3e22)
- Bug 1255710 - Part 0: Rename test_animation_property_state.html to test_animation_performance_warning.html. r=birtles (7c463acc9d)
- Bug 1255710 - Part 1: Remove all unnecessary t.step_func. r=birtles (b8586a3f6c)
- Bug 1255710 - Part 2: Enable tests for 'transform-style: preserve-3d'. r=birtles (35038639a8)
- Bug 1254840 - Use longer animation duration to avoid intermittent failures on slow platforms. r=dholbert (a0574ebd59)
- Bug 1254881 - Fix animation duration in dom/animation/test/chrome/test_running_on_compositor.html. r=hiro (db038a67ec)
- Bug 1256503 - Part 1: Use MS_PER_SEC instead of human-misreadable digits in animation tests. r=dholbert (ad420d4760)
- Bug 1256503 - Part 2: Increase some test animation durations to be at least 100 seconds. r=dholbert (8ea14b30f0)
- Bug 1244633 - Part 1: implement AnimationEffectTiming delay. r=birtles (94d1be534a)
- Bug 1244633 - Part 2: append tests for delay. r=birtles (cd685f1fe4)
- Bug 1244643 - Part 2: Append tests for easing. r=hiro (9f563a4636)
- Bug 1263631 - Update web-platform-tests to revision 8d896c2015ab1e50ad00a0013700f87813d9364c, a=testonly (71b25211b1)
- Bug 1244643 - Part 3: Move common test cases to a new file. r=hiro (7ee5afd9db)
- Bug 1255718. Remove the unused JSContext argument of AudioBuffer::Create. r=ehsan (c7d2112794)
- Bug 684208 - make dispatchEvent()'s return value to follow the spec, r=masayuki (4a8372e2fb)
- Bug 1223980 - Add iterable<ArrayBuffer,MediaKeyStatus> to MediaKeyStatusMap. r=bz (bcc52aabde)
- Bug 1260417 - Part a: Add a comment about the compartment of CallbackObject::mCallback; r=bz (2abca927f9)
- Bug 1260417 - Part c: Stop mentioning requests around CallSetup::mRootedCallable; r=bz (bb507b8f40)
- Bug 1260417 - Part b: Depend on AutoEntryScript to find an appropriate JSContext CallSetup; r=bz (e1b8fd132b)
- remove specific PM check (d7fae861af)
- minor cleanup (a47c325ad1)
- Bug 1254858: P4. Allow to pass mimetype in constructor. r=kentuckyfriedtakahe (3627f6bb0a)
- Bug 1254858: P5. Add h264 decoding gtest. r=kentuckyfriedtakahe (0bb7873e4f)
- Bug 1254858: P6. Add VP9 decoding gtest. r=kentuckyfriedtakahe (6940369a73)
- Bug 1254858: P8. Change default preferences value if prefs don't exist. r=kentuckyfriedtakahe (1516f43986)
- Bug 1247866: Avoid modifying hashtable during iteration, when iterating over redirects for saved files, to avoid tripping fatal assertion. r=njn (94f77efaad)
- bug 1230065 consider arrow size in dropdown minimum widget size r=acomminos (cd67908374)
- bug 1261277 use GtkTextView to get an appropriate color for resizers r=acomminos (b8b2df0ebf)
- bug 1197165 apply tooltip style class when creating window instead of when drawing r=acomminos (c58078774f)
- Bug 1257811 - set min-height for input widgets. r=karlt (43c5507346)
- bug 1199602 give existing wrap_gtk_window_check_resize internal linkage r=acomminos (ef8fe19a89)
- bug 1199602 emit resume-events on GdkFrameClock if flush/resume not balanced at dispose r=acomminos (16d79ac0cd)
- Bug 1249604 - Don't use gtk_drag_set_icon_surface on GTK versions that use X SHAPE for dnd with cairo. r=karlt (3e7b1f3aaf)
- Bug 1262634 - Avoid undefined reference to moz_gtk_get_entry_min_height in builds specifying cairo-gtk2 toolkit. r=karlt (112c35a394)
2024-05-08 09:45:48 +08:00

334 lines
13 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/CallbackObject.h"
#include "mozilla/dom/BindingUtils.h"
#include "jsfriendapi.h"
#include "nsIScriptGlobalObject.h"
#include "nsIXPConnect.h"
#include "nsIScriptContext.h"
#include "nsPIDOMWindow.h"
#include "nsJSUtils.h"
#include "nsIScriptSecurityManager.h"
#include "xpcprivate.h"
#include "WorkerPrivate.h"
#include "nsGlobalWindow.h"
#include "WorkerScope.h"
#include "jsapi.h"
#include "nsJSPrincipals.h"
namespace mozilla {
namespace dom {
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CallbackObject)
NS_INTERFACE_MAP_ENTRY(mozilla::dom::CallbackObject)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(CallbackObject)
NS_IMPL_CYCLE_COLLECTING_RELEASE(CallbackObject)
NS_IMPL_CYCLE_COLLECTION_CLASS(CallbackObject)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CallbackObject)
tmp->DropJSObjects();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIncumbentGlobal)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CallbackObject)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIncumbentGlobal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CallbackObject)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCallback)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCreationStack)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mIncumbentJSGlobal)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
ErrorResult& aRv,
const char* aExecutionReason,
ExceptionHandling aExceptionHandling,
JSCompartment* aCompartment,
bool aIsJSImplementedWebIDL)
: mCx(nullptr)
, mCompartment(aCompartment)
, mErrorResult(aRv)
, mExceptionHandling(aExceptionHandling)
, mIsMainThread(NS_IsMainThread())
{
if (mIsMainThread) {
nsContentUtils::EnterMicroTask();
}
// Compute the caller's subject principal (if necessary) early, before we
// do anything that might perturb the relevant state.
nsIPrincipal* webIDLCallerPrincipal = nullptr;
if (aIsJSImplementedWebIDL) {
webIDLCallerPrincipal = nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
}
// First, find the real underlying callback.
JSObject* realCallback = js::UncheckedUnwrap(aCallback->CallbackPreserveColor());
nsIGlobalObject* globalObject = nullptr;
JSContext* cx;
{
// Bug 955660: we cannot do "proper" rooting here because we need the
// global to get a context. Everything here is simple getters that cannot
// GC, so just paper over the necessary dataflow inversion.
JS::AutoSuppressGCAnalysis nogc;
if (mIsMainThread) {
// Now get the global for this callback. Note that for the case of
// JS-implemented WebIDL we never have a window here.
nsGlobalWindow* win =
aIsJSImplementedWebIDL ? nullptr : xpc::WindowGlobalOrNull(realCallback);
if (win) {
MOZ_ASSERT(win->IsInnerWindow());
// We don't want to run script in windows that have been navigated away
// from.
if (!win->HasActiveDocument()) {
return;
}
globalObject = win;
} else {
// No DOM Window. Store the global.
JSObject* glob = js::GetGlobalForObjectCrossCompartment(realCallback);
globalObject = xpc::NativeGlobal(glob);
MOZ_ASSERT(globalObject);
}
} else {
JSObject *global = js::GetGlobalForObjectCrossCompartment(realCallback);
globalObject = workers::GetGlobalObjectForGlobal(global);
MOZ_ASSERT(globalObject);
}
// Bail out if there's no useful global. This seems to happen intermittently
// on gaia-ui tests, probably because nsInProcessTabChildGlobal is returning
// null in some kind of teardown state.
if (!globalObject->GetGlobalJSObject()) {
return;
}
// Off the main thread, AutoEntryScript expects us to pass a JSContext.
mAutoEntryScript.emplace(globalObject, aExecutionReason, mIsMainThread,
mIsMainThread ? nullptr
: workers::GetCurrentThreadJSContext());
mAutoEntryScript->SetWebIDLCallerPrincipal(webIDLCallerPrincipal);
nsIGlobalObject* incumbent = aCallback->IncumbentGlobalOrNull();
if (incumbent) {
// The callback object traces its incumbent JS global, so in general it
// should be alive here. However, it's possible that we could run afoul
// of the same IPC global weirdness described above, wherein the
// nsIGlobalObject has severed its reference to the JS global. Let's just
// be safe here, so that nobody has to waste a day debugging gaia-ui tests.
if (!incumbent->GetGlobalJSObject()) {
return;
}
mAutoIncumbentScript.emplace(incumbent);
}
cx = mAutoEntryScript->cx();
// Unmark the callable (by invoking Callback() and not the CallbackPreserveColor()
// variant), and stick it in a Rooted before it can go gray again.
// Nothing before us in this function can trigger a CC, so it's safe to wait
// until here it do the unmark. This allows us to construct mRootedCallable
// with the cx from mAutoEntryScript, avoiding the cost of finding another
// JSContext. (Rooted<> does not care about requests or compartments.)
mRootedCallable.emplace(cx, aCallback->Callback());
}
// JS-implemented WebIDL is always OK to run, since it runs with Chrome
// privileges anyway.
if (mIsMainThread && !aIsJSImplementedWebIDL) {
// Check that it's ok to run this callback at all.
// Make sure to use realCallback to get the global of the callback object,
// not the wrapper.
bool allowed = nsContentUtils::GetSecurityManager()->
ScriptAllowed(js::GetGlobalForObjectCrossCompartment(realCallback));
if (!allowed) {
return;
}
}
mAsyncStack.emplace(cx, aCallback->GetCreationStack());
if (*mAsyncStack) {
mAsyncStackSetter.emplace(cx, *mAsyncStack, aExecutionReason);
}
// Enter the compartment of our callback, so we can actually work with it.
//
// Note that if the callback is a wrapper, this will not be the same
// compartment that we ended up in with mAutoEntryScript above, because the
// entry point is based off of the unwrapped callback (realCallback).
mAc.emplace(cx, *mRootedCallable);
// And now we're ready to go.
mCx = cx;
}
bool
CallbackObject::CallSetup::ShouldRethrowException(JS::Handle<JS::Value> aException)
{
if (mExceptionHandling == eRethrowExceptions) {
if (!mCompartment) {
// Caller didn't ask us to filter for only exceptions we subsume.
return true;
}
// On workers, we don't have nsIPrincipals to work with. But we also only
// have one compartment, so check whether mCompartment is the same as the
// current compartment of mCx.
if (mCompartment == js::GetContextCompartment(mCx)) {
return true;
}
MOZ_ASSERT(NS_IsMainThread());
// At this point mCx is in the compartment of our unwrapped callback, so
// just check whether the principal of mCompartment subsumes that of the
// current compartment/global of mCx.
nsIPrincipal* callerPrincipal =
nsJSPrincipals::get(JS_GetCompartmentPrincipals(mCompartment));
nsIPrincipal* calleePrincipal = nsContentUtils::SubjectPrincipal();
if (callerPrincipal->SubsumesConsideringDomain(calleePrincipal)) {
return true;
}
}
MOZ_ASSERT(mCompartment);
// Now we only want to throw an exception to the caller if the object that was
// thrown is in the caller compartment (which we stored in mCompartment).
if (!aException.isObject()) {
return false;
}
JS::Rooted<JSObject*> obj(mCx, &aException.toObject());
obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
return js::GetObjectCompartment(obj) == mCompartment;
}
CallbackObject::CallSetup::~CallSetup()
{
// To get our nesting right we have to destroy our JSAutoCompartment first.
// In particular, we want to do this before we try reporting any exceptions,
// so we end up reporting them while in the compartment of our entry point,
// not whatever cross-compartment wrappper mCallback might be.
// Be careful: the JSAutoCompartment might not have been constructed at all!
mAc.reset();
// Now, if we have a JSContext, report any pending errors on it, unless we
// were told to re-throw them.
if (mCx) {
bool needToDealWithException = mAutoEntryScript->HasException();
if ((mCompartment && mExceptionHandling == eRethrowContentExceptions) ||
mExceptionHandling == eRethrowExceptions) {
mErrorResult.MightThrowJSException();
if (needToDealWithException) {
JS::Rooted<JS::Value> exn(mCx);
if (mAutoEntryScript->PeekException(&exn) &&
ShouldRethrowException(exn)) {
mAutoEntryScript->ClearException();
MOZ_ASSERT(!mAutoEntryScript->HasException());
mErrorResult.ThrowJSException(mCx, exn);
needToDealWithException = false;
}
}
}
if (needToDealWithException) {
// Either we're supposed to report our exceptions, or we're supposed to
// re-throw them but we failed to get the exception value. Either way,
// just report the pending exception, if any.
//
// We don't use nsJSUtils::ReportPendingException here because all it
// does at this point is JS_SaveFrameChain and enter a compartment around
// a JS_ReportPendingException call. But our mAutoEntryScript should
// already do a JS_SaveFrameChain and we are already in the compartment
// we want to be in, so all nsJSUtils::ReportPendingException would do is
// screw up our compartment, which is exactly what we do not want.
//
// XXXbz FIXME: bug 979525 means we don't always JS_SaveFrameChain here,
// so we need to go ahead and do that. This is also the reason we don't
// just rely on ~AutoJSAPI reporting the exception for us. I think if we
// didn't need to JS_SaveFrameChain here, we could just rely on that.
JS::Rooted<JSObject*> oldGlobal(mCx, JS::CurrentGlobalOrNull(mCx));
MOZ_ASSERT(oldGlobal, "How can we not have a global here??");
bool saved = JS_SaveFrameChain(mCx);
// Make sure the JSAutoCompartment goes out of scope before the
// JS_RestoreFrameChain call!
{
JSAutoCompartment ac(mCx, oldGlobal);
MOZ_ASSERT(!JS::DescribeScriptedCaller(mCx),
"Our comment above about JS_SaveFrameChain having been "
"called is a lie?");
// Note that we don't JS_ReportPendingException here because we want to
// go through our AutoEntryScript's reporting mechanism instead, since
// it currently owns error reporting.
mAutoEntryScript->ReportException();
}
if (saved) {
JS_RestoreFrameChain(mCx);
}
if (mErrorResult.IsJSContextException()) {
// XXXkhuey bug 1117269.
// This isn't true anymore ... so throw something else.
mErrorResult.Throw(NS_ERROR_UNEXPECTED);
}
}
}
mAutoIncumbentScript.reset();
mAutoEntryScript.reset();
// It is important that this is the last thing we do, after leaving the
// compartment and undoing all our entry/incumbent script changes
if (mIsMainThread) {
nsContentUtils::LeaveMicroTask();
}
}
already_AddRefed<nsISupports>
CallbackObjectHolderBase::ToXPCOMCallback(CallbackObject* aCallback,
const nsIID& aIID) const
{
MOZ_ASSERT(NS_IsMainThread());
if (!aCallback) {
return nullptr;
}
// We don't init the AutoJSAPI with our callback because we don't want it
// reporting errors to its global's onerror handlers.
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
JS::Rooted<JSObject*> callback(cx, aCallback->Callback());
JSAutoCompartment ac(cx, callback);
RefPtr<nsXPCWrappedJS> wrappedJS;
nsresult rv =
nsXPCWrappedJS::GetNewOrUsed(callback, aIID, getter_AddRefs(wrappedJS));
if (NS_FAILED(rv) || !wrappedJS) {
return nullptr;
}
nsCOMPtr<nsISupports> retval;
rv = wrappedJS->QueryInterface(aIID, getter_AddRefs(retval));
if (NS_FAILED(rv)) {
return nullptr;
}
return retval.forget();
}
} // namespace dom
} // namespace mozilla