Backed out changeset 5937ad352b2d (bug 1542024) for perma failing 406106-1.html CLOSED TREE

This commit is contained in:
Ciure Andrei 2019-04-09 00:12:32 +03:00
parent 8d88b9a596
commit 3ff6ff6d6f
6 changed files with 127 additions and 111 deletions

View File

@ -323,10 +323,10 @@ var listener = {
}
// In the world before bug 997440, exceptions were getting lost because of
// the arbitrary JSContext being used in nsXPCWrappedJS::CallMethod.
// the arbitrary JSContext being used in nsXPCWrappedJSClass::CallMethod.
// In the new world, the wanderers have returned. However, because of the,
// currently very-broken, exception reporting machinery in
// nsXPCWrappedJS these get reported as errors to the console, even if
// XPCWrappedJSClass these get reported as errors to the console, even if
// there's actually JS on the stack above that will catch them. If we
// throw an error here because of them our tests start failing. So, we'll
// just dump the message to the logs instead, to make sure the information

View File

@ -2226,7 +2226,7 @@ class WrappedJSHolder : public nsISupports {
NS_IMPL_ADDREF(WrappedJSHolder)
NS_IMPL_RELEASE(WrappedJSHolder)
// nsINamed is always supported by nsXPCWrappedJS::DelegatedQueryInterface().
// nsINamed is always supported by nsXPCWrappedJSClass.
// We expose this interface only for the identity in telemetry analysis.
NS_INTERFACE_TABLE_HEAD(WrappedJSHolder)
if (aIID.Equals(NS_GET_IID(nsINamed))) {

View File

@ -176,7 +176,7 @@ nsXPCWrappedJS::AggregatedQueryInterface(REFNSIID aIID, void** aInstancePtr) {
return NS_OK;
}
return DelegatedQueryInterface(aIID, aInstancePtr);
return nsXPCWrappedJSClass::DelegatedQueryInterface(this, aIID, aInstancePtr);
}
NS_IMETHODIMP
@ -227,7 +227,7 @@ nsXPCWrappedJS::QueryInterface(REFNSIID aIID, void** aInstancePtr) {
// else...
return DelegatedQueryInterface(aIID, aInstancePtr);
return nsXPCWrappedJSClass::DelegatedQueryInterface(this, aIID, aInstancePtr);
}
// For a description of nsXPCWrappedJS lifetime and reference counting, see
@ -329,12 +329,13 @@ nsresult nsXPCWrappedJS::GetNewOrUsed(JSContext* cx, JS::HandleObject jsObj,
MOZ_RELEASE_ASSERT(js::GetContextCompartment(cx) ==
js::GetObjectCompartment(jsObj));
const nsXPTInterfaceInfo* info = GetInterfaceInfo(aIID);
const nsXPTInterfaceInfo* info = nsXPCWrappedJSClass::GetInterfaceInfo(aIID);
if (!info) {
return NS_ERROR_FAILURE;
}
JS::RootedObject rootJSObj(cx, GetRootJSObject(cx, jsObj));
JS::RootedObject rootJSObj(cx,
nsXPCWrappedJSClass::GetRootJSObject(cx, jsObj));
if (!rootJSObj) {
return NS_ERROR_FAILURE;
}
@ -365,7 +366,7 @@ nsresult nsXPCWrappedJS::GetNewOrUsed(JSContext* cx, JS::HandleObject jsObj,
// root wrapper, and the wrapper we are trying to make isn't
// a root.
const nsXPTInterfaceInfo* rootInfo =
GetInterfaceInfo(NS_GET_IID(nsISupports));
nsXPCWrappedJSClass::GetInterfaceInfo(NS_GET_IID(nsISupports));
if (!rootInfo) {
return NS_ERROR_FAILURE;
}
@ -388,7 +389,10 @@ nsresult nsXPCWrappedJS::GetNewOrUsed(JSContext* cx, JS::HandleObject jsObj,
nsXPCWrappedJS::nsXPCWrappedJS(JSContext* cx, JSObject* aJSObj,
const nsXPTInterfaceInfo* aInfo,
nsXPCWrappedJS* root, nsresult* rv)
: mJSObj(aJSObj), mInfo(aInfo), mRoot(root ? root : this), mNext(nullptr) {
: mJSObj(aJSObj),
mInfo(aInfo),
mRoot(root ? root : this),
mNext(nullptr) {
*rv = InitStub(mInfo->IID());
// Continue even in the failure case, so that our refcounting/Destroy
// behavior works correctly.
@ -576,6 +580,19 @@ nsXPCWrappedJS* nsXPCWrappedJS::FindInherited(REFNSIID aIID) {
return nullptr;
}
NS_IMETHODIMP
nsXPCWrappedJS::CallMethod(uint16_t methodIndex, const nsXPTMethodInfo* info,
nsXPTCMiniVariant* params) {
// Do a release-mode assert against accessing nsXPCWrappedJS off-main-thread.
MOZ_RELEASE_ASSERT(NS_IsMainThread(),
"nsXPCWrappedJS::CallMethod called off main thread");
if (!IsValid()) {
return NS_ERROR_UNEXPECTED;
}
return nsXPCWrappedJSClass::CallMethod(this, methodIndex, info, params);
}
NS_IMETHODIMP
nsXPCWrappedJS::GetInterfaceIID(nsIID** iid) {
MOZ_ASSERT(iid, "bad param");

View File

@ -96,7 +96,8 @@ class MOZ_STACK_CLASS AutoSavePendingResult {
};
// static
const nsXPTInterfaceInfo* nsXPCWrappedJS::GetInterfaceInfo(REFNSIID aIID) {
const nsXPTInterfaceInfo*
nsXPCWrappedJSClass::GetInterfaceInfo(REFNSIID aIID) {
const nsXPTInterfaceInfo* info = nsXPTInterfaceInfo::ByIID(aIID);
if (!info) {
return nullptr;
@ -110,10 +111,10 @@ const nsXPTInterfaceInfo* nsXPCWrappedJS::GetInterfaceInfo(REFNSIID aIID) {
}
// static
JSObject* nsXPCWrappedJS::CallQueryInterfaceOnJSObject(JSContext* cx,
JSObject* jsobjArg,
HandleObject scope,
REFNSIID aIID) {
JSObject* nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(JSContext* cx,
JSObject* jsobjArg,
HandleObject scope,
REFNSIID aIID) {
js::AssertSameCompartment(scope, jsobjArg);
RootedObject jsobj(cx, jsobjArg);
@ -304,11 +305,12 @@ nsCString GetFunctionName(JSContext* cx, HandleObject obj) {
/***************************************************************************/
// static
nsresult nsXPCWrappedJS::DelegatedQueryInterface(REFNSIID aIID,
void** aInstancePtr) {
nsresult nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self,
REFNSIID aIID,
void** aInstancePtr) {
if (aIID.Equals(NS_GET_IID(nsIXPConnectJSObjectHolder))) {
nsCOMPtr<nsIXPConnectJSObjectHolder> rval(this);
rval.forget(aInstancePtr);
NS_ADDREF(self);
*aInstancePtr = (void*)static_cast<nsIXPConnectJSObjectHolder*>(self);
return NS_OK;
}
@ -323,7 +325,7 @@ nsresult nsXPCWrappedJS::DelegatedQueryInterface(REFNSIID aIID,
// We check both nativeGlobal and nativeGlobal->GetGlobalJSObject() even
// though we have derived nativeGlobal from the JS global, because we know
// there are cases where this can happen. See bug 1094953.
RootedObject obj(RootingCx(), GetJSObject());
RootedObject obj(RootingCx(), self->GetJSObject());
nsIGlobalObject* nativeGlobal = NativeGlobal(js::UncheckedUnwrap(obj));
NS_ENSURE_TRUE(nativeGlobal, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(nativeGlobal->GetGlobalJSObject(), NS_ERROR_FAILURE);
@ -335,18 +337,16 @@ nsresult nsXPCWrappedJS::DelegatedQueryInterface(REFNSIID aIID,
return NS_NOINTERFACE;
}
// We now need to enter the realm of the actual JSObject* we are pointing at.
// But that may be a cross-compartment wrapper and therefore not have a
// well-defined realm, so enter the realm of the global that we grabbed back
// when we started pointing to our JSObject*.
RootedObject objScope(RootingCx(), GetJSObjectGlobal());
// We passed the unwrapped object's global to AutoEntryScript so we now need
// to enter the realm corresponding with the (maybe wrapper) object.
RootedObject objScope(RootingCx(), self->GetJSObjectGlobal());
JSAutoRealm ar(aes.cx(), objScope);
// We support nsISupportsWeakReference iff the root wrapped JSObject
// claims to support it in its QueryInterface implementation.
if (aIID.Equals(NS_GET_IID(nsISupportsWeakReference))) {
// We only want to expose one implementation from our aggregate.
nsXPCWrappedJS* root = GetRootWrapper();
nsXPCWrappedJS* root = self->GetRootWrapper();
RootedObject rootScope(ccx, root->GetJSObjectGlobal());
// Fail if JSObject doesn't claim support for nsISupportsWeakReference
@ -385,11 +385,11 @@ nsresult nsXPCWrappedJS::DelegatedQueryInterface(REFNSIID aIID,
}
// Checks for any existing wrapper explicitly constructed for this iid.
// This includes the current wrapper. This also deals with the
// This includes the current 'self' wrapper. This also deals with the
// nsISupports case (for which it returns mRoot).
// Also check if asking for an interface from which one of our wrappers
// inherits.
if (nsXPCWrappedJS* sibling = FindOrFindInherited(aIID)) {
if (nsXPCWrappedJS* sibling = self->FindOrFindInherited(aIID)) {
NS_ADDREF(sibling);
*aInstancePtr = sibling->GetXPTCStub();
return NS_OK;
@ -457,7 +457,8 @@ nsresult nsXPCWrappedJS::DelegatedQueryInterface(REFNSIID aIID,
}
// static
JSObject* nsXPCWrappedJS::GetRootJSObject(JSContext* cx, JSObject* aJSObjArg) {
JSObject* nsXPCWrappedJSClass::GetRootJSObject(JSContext* cx,
JSObject* aJSObjArg) {
RootedObject aJSObj(cx, aJSObjArg);
RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
JSObject* result =
@ -469,10 +470,10 @@ JSObject* nsXPCWrappedJS::GetRootJSObject(JSContext* cx, JSObject* aJSObjArg) {
}
// static
bool nsXPCWrappedJS::GetArraySizeFromParam(const nsXPTMethodInfo* method,
const nsXPTType& type,
nsXPTCMiniVariant* nativeParams,
uint32_t* result) {
bool nsXPCWrappedJSClass::GetArraySizeFromParam(const nsXPTMethodInfo* method,
const nsXPTType& type,
nsXPTCMiniVariant* nativeParams,
uint32_t* result) {
if (type.Tag() != nsXPTType::T_LEGACY_ARRAY &&
type.Tag() != nsXPTType::T_PSTRING_SIZE_IS &&
type.Tag() != nsXPTType::T_PWSTRING_SIZE_IS) {
@ -500,10 +501,9 @@ bool nsXPCWrappedJS::GetArraySizeFromParam(const nsXPTMethodInfo* method,
}
// static
bool nsXPCWrappedJS::GetInterfaceTypeFromParam(const nsXPTMethodInfo* method,
const nsXPTType& type,
nsXPTCMiniVariant* nativeParams,
nsID* result) {
bool nsXPCWrappedJSClass::GetInterfaceTypeFromParam(
const nsXPTMethodInfo* method, const nsXPTType& type,
nsXPTCMiniVariant* nativeParams, nsID* result) {
result->Clear();
const nsXPTType& inner = type.InnermostType();
@ -541,9 +541,9 @@ bool nsXPCWrappedJS::GetInterfaceTypeFromParam(const nsXPTMethodInfo* method,
}
// static
void nsXPCWrappedJS::CleanupOutparams(const nsXPTMethodInfo* info,
nsXPTCMiniVariant* nativeParams,
bool inOutOnly, uint8_t count) {
void nsXPCWrappedJSClass::CleanupOutparams(const nsXPTMethodInfo* info,
nsXPTCMiniVariant* nativeParams,
bool inOutOnly, uint8_t count) {
// clean up any 'out' params handed in
for (uint8_t i = 0; i < count; i++) {
const nsXPTParamInfo& param = info->GetParam(i);
@ -577,12 +577,10 @@ void nsXPCWrappedJS::CleanupOutparams(const nsXPTMethodInfo* info,
}
}
nsresult nsXPCWrappedJS::CheckForException(XPCCallContext& ccx,
AutoEntryScript& aes,
HandleObject aObj,
const char* aPropertyName,
const char* anInterfaceName,
Exception* aSyntheticException) {
nsresult nsXPCWrappedJSClass::CheckForException(
XPCCallContext& ccx, AutoEntryScript& aes, HandleObject aObj,
const char* aPropertyName, const char* anInterfaceName,
Exception* aSyntheticException) {
JSContext* cx = ccx.GetJSContext();
MOZ_ASSERT(cx == aes.cx());
RefPtr<Exception> xpc_exception = aSyntheticException;
@ -737,17 +735,10 @@ nsresult nsXPCWrappedJS::CheckForException(XPCCallContext& ccx,
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsXPCWrappedJS::CallMethod(uint16_t methodIndex, const nsXPTMethodInfo* info,
nsXPTCMiniVariant* nativeParams) {
// Do a release-mode assert against accessing nsXPCWrappedJS off-main-thread.
MOZ_RELEASE_ASSERT(NS_IsMainThread(),
"nsXPCWrappedJS::CallMethod called off main thread");
if (!IsValid()) {
return NS_ERROR_UNEXPECTED;
}
nsresult nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper,
uint16_t methodIndex,
const nsXPTMethodInfo* info,
nsXPTCMiniVariant* nativeParams) {
Value* sp = nullptr;
Value* argv = nullptr;
uint8_t i;
@ -760,7 +751,7 @@ nsXPCWrappedJS::CallMethod(uint16_t methodIndex, const nsXPTMethodInfo* info,
// We're about to call into script via an XPCWrappedJS, so we need an
// AutoEntryScript. This is probably Gecko-specific at this point, and
// definitely will be when we turn off XPConnect for the web.
RootedObject obj(RootingCx(), GetJSObject());
RootedObject obj(RootingCx(), wrapper->GetJSObject());
nsIGlobalObject* nativeGlobal = NativeGlobal(js::UncheckedUnwrap(obj));
AutoEntryScript aes(nativeGlobal, "XPCWrappedJS method call",
/* aIsMainThread = */ true);
@ -775,7 +766,7 @@ nsXPCWrappedJS::CallMethod(uint16_t methodIndex, const nsXPTMethodInfo* info,
return NS_ERROR_FAILURE;
}
const nsXPTInterfaceInfo* interfaceInfo = GetInfo();
const nsXPTInterfaceInfo* interfaceInfo = wrapper->GetInfo();
JS::RootedId id(cx);
const char* name;
nsAutoCString symbolName;
@ -790,11 +781,9 @@ nsXPCWrappedJS::CallMethod(uint16_t methodIndex, const nsXPTMethodInfo* info,
}
}
// We now need to enter the realm of the actual JSObject* we are pointing at.
// But that may be a cross-compartment wrapper and therefore not have a
// well-defined realm, so enter the realm of the global that we grabbed back
// when we started pointing to our JSObject*.
RootedObject scope(cx, GetJSObjectGlobal());
// We passed the unwrapped object's global to AutoEntryScript so we now need
// to enter the realm corresponding with the (maybe wrapper) object.
RootedObject scope(cx, wrapper->GetJSObjectGlobal());
JSAutoRealm ar(cx, scope);
// [optional_argc] has a different calling convention, which we don't
@ -1101,8 +1090,8 @@ JSObject* xpc::NewOutObject(JSContext* cx) {
}
// static
void nsXPCWrappedJS::DebugDumpInterfaceInfo(const nsXPTInterfaceInfo* aInfo,
int16_t depth) {
void nsXPCWrappedJSClass::DebugDump(const nsXPTInterfaceInfo* aInfo,
int16_t depth) {
#ifdef DEBUG
depth--;
XPC_LOG_ALWAYS(("nsXPTInterfaceInfo @ %p = ", aInfo));

View File

@ -1589,6 +1589,58 @@ class XPCWrappedNative final : public nsIXPConnectWrappedNative {
****************************************************************************
***************************************************************************/
/*************************/
// nsXPCWrappedJSClass contains a number of helper methods for using
// nsXPTInterfaceInfo and nsXPCWrappedJS.
class nsXPCWrappedJSClass final {
public:
static const nsXPTInterfaceInfo* GetInterfaceInfo(REFNSIID aIID);
static void DebugDump(const nsXPTInterfaceInfo* aInfo, int16_t depth);
static nsresult DelegatedQueryInterface(nsXPCWrappedJS* self, REFNSIID aIID,
void** aInstancePtr);
static JSObject* GetRootJSObject(JSContext* cx, JSObject* aJSObj);
static nsresult CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
const nsXPTMethodInfo* info,
nsXPTCMiniVariant* params);
static JSObject* CallQueryInterfaceOnJSObject(JSContext* cx, JSObject* jsobj,
JS::HandleObject scope,
REFNSIID aIID);
private:
// aObj is the nsXPCWrappedJS's object. We used this as the callee (or |this|
// if getter or setter).
// aSyntheticException, if not null, is the exception we should be using.
// If null, look for an exception on the JSContext hanging off the
// XPCCallContext.
static nsresult CheckForException(
XPCCallContext& ccx, mozilla::dom::AutoEntryScript& aes,
JS::HandleObject aObj, const char* aPropertyName,
const char* anInterfaceName,
mozilla::dom::Exception* aSyntheticException = nullptr);
nsXPCWrappedJSClass() = delete;
~nsXPCWrappedJSClass() = delete;
static bool GetArraySizeFromParam(const nsXPTMethodInfo* method,
const nsXPTType& type,
nsXPTCMiniVariant* params,
uint32_t* result);
static bool GetInterfaceTypeFromParam(const nsXPTMethodInfo* method,
const nsXPTType& type,
nsXPTCMiniVariant* params,
nsID* result);
static void CleanupOutparams(const nsXPTMethodInfo* info,
nsXPTCMiniVariant* nativeParams, bool inOutOnly,
uint8_t count);
};
/*************************/
// nsXPCWrappedJS is a wrapper for a single JSObject for use from native code.
// nsXPCWrappedJS objects are chained together to represent the various
@ -1608,9 +1660,8 @@ class nsXPCWrappedJS final : protected nsAutoXPTCStub,
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(nsXPCWrappedJS,
nsIXPConnectWrappedJS)
// This method is defined in XPCWrappedJSClass.cpp to preserve VCS blame.
NS_IMETHOD CallMethod(uint16_t methodIndex, const nsXPTMethodInfo* info,
nsXPTCMiniVariant* nativeParams) override;
nsXPTCMiniVariant* params) override;
/*
* This is rarely called directly. Instead one usually calls
@ -1684,19 +1735,14 @@ class nsXPCWrappedJS final : protected nsAutoXPTCStub,
void TraceJS(JSTracer* trc);
// This method is defined in XPCWrappedJSClass.cpp to preserve VCS blame.
static void DebugDumpInterfaceInfo(const nsXPTInterfaceInfo* aInfo,
int16_t depth);
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
virtual ~nsXPCWrappedJS();
protected:
nsXPCWrappedJS() = delete;
nsXPCWrappedJS(JSContext* cx, JSObject* aJSObj,
const nsXPTInterfaceInfo* aInfo, nsXPCWrappedJS* root,
nsresult* rv);
nsXPCWrappedJS(JSContext* cx, JSObject* aJSObj, const nsXPTInterfaceInfo* aInfo,
nsXPCWrappedJS* root, nsresult* rv);
bool CanSkip();
void Destroy();
@ -1707,42 +1753,6 @@ class nsXPCWrappedJS final : protected nsAutoXPTCStub,
return js::GetObjectCompartment(mJSObj.unbarrieredGet());
}
// These methods are defined in XPCWrappedJSClass.cpp to preserve VCS blame.
static const nsXPTInterfaceInfo* GetInterfaceInfo(REFNSIID aIID);
nsresult DelegatedQueryInterface(REFNSIID aIID, void** aInstancePtr);
static JSObject* GetRootJSObject(JSContext* cx, JSObject* aJSObj);
static JSObject* CallQueryInterfaceOnJSObject(JSContext* cx, JSObject* jsobj,
JS::HandleObject scope,
REFNSIID aIID);
// aObj is the nsXPCWrappedJS's object. We used this as the callee (or |this|
// if getter or setter).
// aSyntheticException, if not null, is the exception we should be using.
// If null, look for an exception on the JSContext hanging off the
// XPCCallContext.
static nsresult CheckForException(
XPCCallContext& ccx, mozilla::dom::AutoEntryScript& aes,
JS::HandleObject aObj, const char* aPropertyName,
const char* anInterfaceName,
mozilla::dom::Exception* aSyntheticException = nullptr);
static bool GetArraySizeFromParam(const nsXPTMethodInfo* method,
const nsXPTType& type,
nsXPTCMiniVariant* params,
uint32_t* result);
static bool GetInterfaceTypeFromParam(const nsXPTMethodInfo* method,
const nsXPTType& type,
nsXPTCMiniVariant* params,
nsID* result);
static void CleanupOutparams(const nsXPTMethodInfo* info,
nsXPTCMiniVariant* nativeParams, bool inOutOnly,
uint8_t count);
JS::Heap<JSObject*> mJSObj;
const nsXPTInterfaceInfo* const mInfo;
nsXPCWrappedJS* mRoot; // If mRoot != this, it is an owning pointer.

View File

@ -33,7 +33,7 @@ function make_fake_appdir() {
}
// Depending on timing we can get requests for other files.
// When we threw an exception here, in the world before bug 997440, this got lost
// because of the arbitrary JSContext being used in nsXPCWrappedJS::CallMethod.
// because of the arbitrary JSContext being used in XPCWrappedJSClass::CallMethod.
// After bug 997440 this gets reported to our window and causes the tests to fail.
// So, we'll just dump out a message to the logs.
dump("WARNING: make_fake_appdir - fake nsIDirectoryServiceProvider - Unexpected getFile for: '" + prop + "'\n");