Bug 993413 - Remove use of JS_Add/Remove*Root in favour of JS::PersistentRooted where possible r=terrence r=bz r=bholley

This commit is contained in:
Jon Coppeard 2014-04-16 09:47:53 +01:00
Родитель f3f1e4c964
Коммит 173bd25321
16 изменённых файлов: 117 добавлений и 217 удалений

Просмотреть файл

@ -1363,17 +1363,10 @@ nsFrameScriptExecutor::DidCreateGlobal()
}
static PLDHashOperator
CachedScriptUnrooter(const nsAString& aKey,
nsFrameScriptObjectExecutorHolder*& aData,
void* aUserArg)
RemoveCachedScriptEntry(const nsAString& aKey,
nsFrameScriptObjectExecutorHolder*& aData,
void* aUserArg)
{
JSContext* cx = static_cast<JSContext*>(aUserArg);
if (aData->mScript) {
JS_RemoveScriptRoot(cx, &aData->mScript);
}
if (aData->mFunction) {
JS_RemoveObjectRoot(cx, &aData->mFunction);
}
delete aData;
return PL_DHASH_REMOVE;
}
@ -1385,7 +1378,7 @@ nsFrameScriptExecutor::Shutdown()
if (sCachedScripts) {
AutoSafeJSContext cx;
NS_ASSERTION(sCachedScripts != nullptr, "Need cached scripts");
sCachedScripts->Enumerate(CachedScriptUnrooter, cx);
sCachedScripts->Enumerate(RemoveCachedScriptEntry, nullptr);
delete sCachedScripts;
sCachedScripts = nullptr;
@ -1528,13 +1521,9 @@ nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL,
// Root the object also for caching.
if (script) {
holder = new nsFrameScriptObjectExecutorHolder(script);
JS_AddNamedScriptRoot(cx, &holder->mScript,
"Cached message manager script");
holder = new nsFrameScriptObjectExecutorHolder(cx, script);
} else {
holder = new nsFrameScriptObjectExecutorHolder(funobj);
JS_AddNamedObjectRoot(cx, &holder->mFunction,
"Cached message manager function");
holder = new nsFrameScriptObjectExecutorHolder(cx, funobj);
}
sCachedScripts->Put(aURL, holder);
}
@ -1922,25 +1911,15 @@ nsSameProcessAsyncMessageBase::nsSameProcessAsyncMessageBase(JSContext* aCx,
nsIPrincipal* aPrincipal)
: mRuntime(js::GetRuntime(aCx)),
mMessage(aMessage),
mCpows(aCpows),
mCpows(aCx, aCpows),
mPrincipal(aPrincipal)
{
if (aData.mDataLength && !mData.copy(aData.mData, aData.mDataLength)) {
NS_RUNTIMEABORT("OOM");
}
if (mCpows && !js_AddObjectRoot(mRuntime, &mCpows)) {
NS_RUNTIMEABORT("OOM");
}
mClosure = aData.mClosure;
}
nsSameProcessAsyncMessageBase::~nsSameProcessAsyncMessageBase()
{
if (mCpows) {
JS_RemoveObjectRootRT(mRuntime, &mCpows);
}
}
void
nsSameProcessAsyncMessageBase::ReceiveMessage(nsISupports* aTarget,
nsFrameMessageManager* aManager)
@ -1951,7 +1930,7 @@ nsSameProcessAsyncMessageBase::ReceiveMessage(nsISupports* aTarget,
data.mDataLength = mData.nbytes();
data.mClosure = mClosure;
SameProcessCpowHolder cpows(mRuntime, JS::Handle<JSObject*>::fromMarkedLocation(&mCpows));
SameProcessCpowHolder cpows(mRuntime, mCpows);
nsRefPtr<nsFrameMessageManager> mm = aManager;
mm->ReceiveMessage(aTarget, mMessage, false, &data, &cpows,

Просмотреть файл

@ -337,7 +337,6 @@ public:
const StructuredCloneData& aData,
JS::Handle<JSObject*> aCpows,
nsIPrincipal* aPrincipal);
~nsSameProcessAsyncMessageBase();
void ReceiveMessage(nsISupports* aTarget, nsFrameMessageManager* aManager);
@ -348,7 +347,7 @@ private:
nsString mMessage;
JSAutoStructuredCloneBuffer mData;
StructuredCloneClosure mClosure;
JSObject* mCpows;
JS::PersistentRooted<JSObject*> mCpows;
nsCOMPtr<nsIPrincipal> mPrincipal;
};
@ -356,19 +355,21 @@ class nsScriptCacheCleaner;
struct nsFrameScriptObjectExecutorHolder
{
nsFrameScriptObjectExecutorHolder(JSScript* aScript) : mScript(aScript), mFunction(nullptr)
nsFrameScriptObjectExecutorHolder(JSContext* aCx, JSScript* aScript)
: mScript(aCx, aScript), mFunction(aCx, nullptr)
{ MOZ_COUNT_CTOR(nsFrameScriptObjectExecutorHolder); }
nsFrameScriptObjectExecutorHolder(JSObject* aFunction) : mScript(nullptr), mFunction(aFunction)
nsFrameScriptObjectExecutorHolder(JSContext* aCx, JSObject* aFunction)
: mScript(aCx, nullptr), mFunction(aCx, aFunction)
{ MOZ_COUNT_CTOR(nsFrameScriptObjectExecutorHolder); }
~nsFrameScriptObjectExecutorHolder()
{ MOZ_COUNT_DTOR(nsFrameScriptObjectExecutorHolder); }
bool WillRunInGlobalScope() { return mScript; }
// We use JS_AddNamed{Script,Object}Root to root these fields explicitly, so
// no need for Heap<T>.
JSScript* mScript;
JSObject* mFunction;
JS::PersistentRooted<JSScript*> mScript;
JS::PersistentRooted<JSObject*> mFunction;
};
class nsFrameScriptObjectExecutorStackHolder;

Просмотреть файл

@ -233,24 +233,16 @@ DOMRequestService::FireDetailedError(nsIDOMDOMRequest* aRequest,
class FireSuccessAsyncTask : public nsRunnable
{
FireSuccessAsyncTask(DOMRequest* aRequest,
FireSuccessAsyncTask(JSContext* aCx,
DOMRequest* aRequest,
const JS::Value& aResult) :
mReq(aRequest),
mResult(aResult),
mIsSetup(false)
mResult(aCx, aResult)
{
}
public:
void
Setup()
{
AutoSafeJSContext cx;
JS_AddValueRoot(cx, &mResult);
mIsSetup = true;
}
// Due to the fact that initialization can fail during shutdown (since we
// can't fetch a js context), set up an initiatization function to make sure
// we can return the failure appropriately
@ -259,8 +251,8 @@ public:
const JS::Value& aResult)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsRefPtr<FireSuccessAsyncTask> asyncTask = new FireSuccessAsyncTask(aRequest, aResult);
asyncTask->Setup();
AutoSafeJSContext cx;
nsRefPtr<FireSuccessAsyncTask> asyncTask = new FireSuccessAsyncTask(cx, aRequest, aResult);
if (NS_FAILED(NS_DispatchToMainThread(asyncTask))) {
NS_WARNING("Failed to dispatch to main thread!");
return NS_ERROR_FAILURE;
@ -271,25 +263,18 @@ public:
NS_IMETHODIMP
Run()
{
mReq->FireSuccess(JS::Handle<JS::Value>::fromMarkedLocation(&mResult));
mReq->FireSuccess(JS::Handle<JS::Value>::fromMarkedLocation(mResult.address()));
return NS_OK;
}
~FireSuccessAsyncTask()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if(!mIsSetup) {
// If we never set up, no reason to unroot
return;
}
AutoSafeJSContext cx;
JS_RemoveValueRoot(cx, &mResult);
}
private:
nsRefPtr<DOMRequest> mReq;
JS::Value mResult;
bool mIsSetup;
JS::PersistentRooted<JS::Value> mResult;
};
class FireErrorAsyncTask : public nsRunnable

Просмотреть файл

@ -161,8 +161,9 @@ static bool
NPObjWrapper_Construct(JSContext *cx, unsigned argc, JS::Value *vp);
static bool
CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject *npobj,
JS::Handle<jsid> id, NPVariant* getPropertyResult, JS::Value *vp);
CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject* npobj,
JS::Handle<jsid> id, NPVariant* getPropertyResult,
JS::MutableHandle<JS::Value> vp);
const JSClass sNPObjectJSWrapperClass =
{
@ -496,7 +497,7 @@ ReportExceptionIfPending(JSContext *cx)
}
nsJSObjWrapper::nsJSObjWrapper(NPP npp)
: mNpp(npp)
: mJSObj(GetJSContext(npp), nullptr), mNpp(npp)
{
MOZ_COUNT_CTOR(nsJSObjWrapper);
OnWrapperCreated();
@ -514,9 +515,6 @@ nsJSObjWrapper::~nsJSObjWrapper()
void
nsJSObjWrapper::ClearJSObject() {
// Unroot the object's JSObject
JS_RemoveObjectRootRT(sJSRuntime, &mJSObj);
// Forget our reference to the JSObject.
mJSObj = nullptr;
}
@ -1022,6 +1020,8 @@ nsJSObjWrapper::GetNewOrUsed(NPP npp, JSContext *cx, JS::Handle<JSObject*> obj)
return nullptr;
}
// Assign mJSObj, rooting the JSObject. Its lifetime is now tied to that of
// the NPObject.
wrapper->mJSObj = obj;
nsJSObjWrapperKey key(obj, npp);
@ -1031,19 +1031,6 @@ nsJSObjWrapper::GetNewOrUsed(NPP npp, JSContext *cx, JS::Handle<JSObject*> obj)
return nullptr;
}
NS_ASSERTION(wrapper->mNpp == npp, "nsJSObjWrapper::mNpp not initialized!");
// Root the JSObject, its lifetime is now tied to that of the
// NPObject.
if (!::JS_AddNamedObjectRoot(cx, &wrapper->mJSObj, "nsJSObjWrapper::mJSObject")) {
NS_ERROR("Failed to root JSObject!");
sJSObjWrappers.remove(key);
_releaseobject(wrapper);
return nullptr;
}
// Add postbarrier for the hashtable key
JS_StoreObjectPostBarrierCallback(cx, JSObjWrapperKeyMarkCallback, obj, wrapper->mNpp);
@ -1271,7 +1258,7 @@ NPObjWrapper_GetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<js
if (success) {
// We return NPObject Member class here to support ambiguous members.
if (hasProperty && hasMethod)
return CreateNPObjectMember(npp, cx, obj, npobj, id, &npv, vp.address());
return CreateNPObjectMember(npp, cx, obj, npobj, id, &npv, vp);
if (hasProperty) {
vp.set(NPVariantToJSVal(npp, cx, &npv));
@ -1294,7 +1281,7 @@ NPObjWrapper_GetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<js
// We return NPObject Member class here to support ambiguous members.
if (hasProperty && hasMethod)
return CreateNPObjectMember(npp, cx, obj, npobj, id, nullptr, vp.address());
return CreateNPObjectMember(npp, cx, obj, npobj, id, nullptr, vp);
if (hasProperty) {
if (npobj->_class->getProperty(npobj, identifier, &npv))
@ -1906,12 +1893,11 @@ LookupNPP(NPObject *npobj)
return entry->mNpp;
}
bool
static bool
CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject* npobj,
JS::Handle<jsid> id, NPVariant* getPropertyResult, JS::Value *vp)
JS::Handle<jsid> id, NPVariant* getPropertyResult,
JS::MutableHandle<JS::Value> vp)
{
NS_ENSURE_TRUE(vp, false);
if (!npobj || !npobj->_class || !npobj->_class->getProperty ||
!npobj->_class->invoke) {
ThrowJSException(cx, "Bad NPObject");
@ -1934,8 +1920,7 @@ CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject* npobj,
return false;
}
*vp = OBJECT_TO_JSVAL(memobj);
::JS_AddValueRoot(cx, vp);
vp.setObject(*memobj);
::JS_SetPrivate(memobj, (void *)memberPrivate);
@ -1953,13 +1938,7 @@ CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject* npobj,
NPBool hasProperty = npobj->_class->getProperty(npobj, identifier,
&npv);
if (!ReportExceptionIfPending(cx)) {
::JS_RemoveValueRoot(cx, vp);
return false;
}
if (!hasProperty) {
::JS_RemoveValueRoot(cx, vp);
if (!ReportExceptionIfPending(cx) || !hasProperty) {
return false;
}
}
@ -1977,8 +1956,6 @@ CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject* npobj,
memberPrivate->methodName = id;
memberPrivate->npp = npp;
::JS_RemoveValueRoot(cx, vp);
return true;
}

Просмотреть файл

@ -41,7 +41,7 @@ extern const JSClass sNPObjectJSWrapperClass;
class nsJSObjWrapper : public NPObject
{
public:
JSObject *mJSObj; /* Added as a GC root. */
JS::PersistentRooted<JSObject *> mJSObj;
const NPP mNpp;
static NPObject *GetNewOrUsed(NPP npp, JSContext *cx,

Просмотреть файл

@ -92,31 +92,18 @@ public:
JS::Handle<JS::Value> aValue,
Promise::PromiseState aState)
: mPromise(aPromise)
, mValue(aValue)
, mValue(CycleCollectedJSRuntime::Get()->Runtime(), aValue)
, mState(aState)
{
MOZ_ASSERT(aPromise);
MOZ_ASSERT(mState != Promise::Pending);
MOZ_COUNT_CTOR(PromiseResolverMixin);
/* It's safe to use unsafeGet() here: the unsafeness comes from the
* possibility of updating the value of mJSObject without triggering the
* barriers. However if the value will always be marked, post barriers
* unnecessary. */
JS_AddNamedValueRootRT(CycleCollectedJSRuntime::Get()->Runtime(), mValue.unsafeGet(),
"PromiseResolverMixin.mValue");
}
virtual ~PromiseResolverMixin()
{
NS_ASSERT_OWNINGTHREAD(PromiseResolverMixin);
MOZ_COUNT_DTOR(PromiseResolverMixin);
/* It's safe to use unsafeGet() here: the unsafeness comes from the
* possibility of updating the value of mJSObject without triggering the
* barriers. However if the value will always be marked, post barriers
* unnecessary. */
JS_RemoveValueRootRT(CycleCollectedJSRuntime::Get()->Runtime(), mValue.unsafeGet());
}
protected:
@ -131,7 +118,7 @@ protected:
private:
nsRefPtr<Promise> mPromise;
JS::Heap<JS::Value> mValue;
JS::PersistentRooted<JS::Value> mValue;
Promise::PromiseState mState;
NS_DECL_OWNINGTHREAD;
};

Просмотреть файл

@ -18,6 +18,7 @@
#include "nsIPrefService.h"
#include "nspr.h"
#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "nsContentUtils.h"
#include "nsCxPusher.h"
#include "nsIScriptSecurityManager.h"
@ -29,14 +30,14 @@ using mozilla::AutoSafeJSContext;
//*****************************************************************************
static JSObject *autoconfigSb = nullptr;
static mozilla::Maybe<JS::PersistentRooted<JSObject *> > autoconfigSb;
nsresult CentralizedAdminPrefManagerInit()
{
nsresult rv;
// If the sandbox is already created, no need to create it again.
if (autoconfigSb)
if (!autoconfigSb.empty())
return NS_OK;
// Grab XPConnect.
@ -57,37 +58,32 @@ nsresult CentralizedAdminPrefManagerInit()
NS_ENSURE_SUCCESS(rv, rv);
// Unwrap, store and root the sandbox.
autoconfigSb = sandbox->GetJSObject();
NS_ENSURE_STATE(autoconfigSb);
autoconfigSb = js::UncheckedUnwrap(autoconfigSb);
JSAutoCompartment ac(cx, autoconfigSb);
if (!JS_AddNamedObjectRoot(cx, &autoconfigSb, "AutoConfig Sandbox"))
return NS_ERROR_FAILURE;
NS_ENSURE_STATE(sandbox->GetJSObject());
autoconfigSb.construct(cx, js::UncheckedUnwrap(sandbox->GetJSObject()));
return NS_OK;
}
nsresult CentralizedAdminPrefManagerFinish()
{
if (autoconfigSb) {
if (!autoconfigSb.empty()) {
AutoSafeJSContext cx;
JSAutoCompartment(cx, autoconfigSb);
JS_RemoveObjectRoot(cx, &autoconfigSb);
autoconfigSb.destroy();
JS_MaybeGC(cx);
}
return NS_OK;
}
nsresult EvaluateAdminConfigScript(const char *js_buffer, size_t length,
const char *filename, bool bGlobalContext,
const char *filename, bool bGlobalContext,
bool bCallbacks, bool skipFirstLine)
{
nsresult rv = NS_OK;
if (skipFirstLine) {
/* In order to protect the privacy of the JavaScript preferences file
/* In order to protect the privacy of the JavaScript preferences file
* from loading by the browser, we make the first line unparseable
* by JavaScript. We must skip that line here before executing
* by JavaScript. We must skip that line here before executing
* the JavaScript code.
*/
unsigned int i = 0;
@ -113,11 +109,11 @@ nsresult EvaluateAdminConfigScript(const char *js_buffer, size_t length,
}
AutoSafeJSContext cx;
JSAutoCompartment ac(cx, autoconfigSb);
JSAutoCompartment ac(cx, autoconfigSb.ref());
nsAutoCString script(js_buffer, length);
JS::RootedValue v(cx);
rv = xpc->EvalInSandboxObject(NS_ConvertASCIItoUTF16(script), filename, cx, autoconfigSb,
rv = xpc->EvalInSandboxObject(NS_ConvertASCIItoUTF16(script), filename, cx, autoconfigSb.ref(),
/* returnStringOnly = */ false, &v);
NS_ENSURE_SUCCESS(rv, rv);

Просмотреть файл

@ -113,7 +113,7 @@ static size_t gMaxStackSize = 128 * sizeof(size_t) * 1024;
static double MAX_TIMEOUT_INTERVAL = 1800.0;
static double gTimeoutInterval = -1.0;
static volatile bool gTimedOut = false;
static JS::Value gTimeoutFunc;
static Maybe<JS::PersistentRootedValue> gTimeoutFunc;
static bool enableDisassemblyDumps = false;
@ -362,11 +362,11 @@ ShellInterruptCallback(JSContext *cx)
return true;
bool result;
if (!gTimeoutFunc.isNull()) {
RootedValue timeoutFunc(cx, gTimeoutFunc.ref());
if (!timeoutFunc.isNull()) {
JS::AutoSaveExceptionState savedExc(cx);
JSAutoCompartment ac(cx, &gTimeoutFunc.toObject());
JSAutoCompartment ac(cx, &timeoutFunc.toObject());
RootedValue rval(cx);
HandleValue timeoutFunc = HandleValue::fromMarkedLocation(&gTimeoutFunc);
if (!JS_CallFunctionValue(cx, JS::NullPtr(), timeoutFunc,
JS::HandleValueArray::empty(), &rval))
{
@ -3303,7 +3303,7 @@ CancelExecution(JSRuntime *rt)
gTimedOut = true;
JS_RequestInterruptCallback(rt);
if (!gTimeoutFunc.isNull()) {
if (!gTimeoutFunc.ref().get().isNull()) {
static const char msg[] = "Script runs for too long, terminating.\n";
#if defined(XP_UNIX) && !defined(JS_THREADSAFE)
/* It is not safe to call fputs from signals. */
@ -3357,7 +3357,7 @@ Timeout(JSContext *cx, unsigned argc, Value *vp)
JS_ReportError(cx, "Second argument must be a timeout function");
return false;
}
gTimeoutFunc = value;
gTimeoutFunc.ref() = value;
}
args.rval().setUndefined();
@ -3538,11 +3538,8 @@ class OffThreadState {
return false;
JS_ASSERT(!token);
JS_ASSERT(!source);
source = newSource;
if (!JS_AddStringRoot(cx, &source))
return false;
source.construct(cx, newSource);
state = COMPILING;
return true;
@ -3552,10 +3549,9 @@ class OffThreadState {
AutoLockMonitor alm(monitor);
JS_ASSERT(state == COMPILING);
JS_ASSERT(!token);
JS_ASSERT(source);
JS_ASSERT(source.ref());
JS_RemoveStringRoot(cx, &source);
source = nullptr;
source.destroy();
state = IDLE;
}
@ -3564,7 +3560,7 @@ class OffThreadState {
AutoLockMonitor alm(monitor);
JS_ASSERT(state == COMPILING);
JS_ASSERT(!token);
JS_ASSERT(source);
JS_ASSERT(source.ref());
JS_ASSERT(newToken);
token = newToken;
@ -3582,9 +3578,8 @@ class OffThreadState {
alm.wait();
}
JS_ASSERT(source);
JS_RemoveStringRoot(cx, &source);
source = nullptr;
JS_ASSERT(source.ref());
source.destroy();
JS_ASSERT(token);
void *holdToken = token;
@ -3597,7 +3592,7 @@ class OffThreadState {
Monitor monitor;
State state;
void *token;
JSString *source;
Maybe<PersistentRootedString> source;
};
static OffThreadState offThreadState;
@ -6162,9 +6157,7 @@ main(int argc, char **argv, char **envp)
if (!SetRuntimeOptions(rt, op))
return 1;
gTimeoutFunc = NullValue();
if (!JS_AddNamedValueRootRT(rt, &gTimeoutFunc, "gTimeoutFunc"))
return 1;
gTimeoutFunc.construct(rt, NullValue());
JS_SetGCParameter(rt, JSGC_MAX_BYTES, 0xffffffff);
#ifdef JSGC_GENERATIONAL
@ -6210,13 +6203,12 @@ main(int argc, char **argv, char **envp)
printf("OOM max count: %u\n", OOM_counter);
#endif
gTimeoutFunc = NullValue();
JS_RemoveValueRootRT(rt, &gTimeoutFunc);
DestroyContext(cx, true);
KillWatchdog();
gTimeoutFunc.destroy();
#ifdef JS_THREADSAFE
for (size_t i = 0; i < workerThreads.length(); i++)
PR_JoinThread(workerThreads[i]);

Просмотреть файл

@ -415,7 +415,7 @@ mozJSComponentLoader::LoadModule(FileLocation &aFile)
if (mModules.Get(spec, &mod))
return mod;
nsAutoPtr<ModuleEntry> entry(new ModuleEntry);
nsAutoPtr<ModuleEntry> entry(new ModuleEntry(mContext));
JSAutoRequest ar(mContext);
RootedValue dummy(mContext);
@ -752,8 +752,8 @@ mozJSComponentLoader::PrepareObjectForLocation(JSCLContextHelper& aCx,
nsresult
mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile,
nsIURI *aURI,
JSObject **aObject,
JSScript **aTableScript,
MutableHandleObject aObject,
MutableHandleScript aTableScript,
char **aLocation,
bool aPropagateExceptions,
MutableHandleValue aException)
@ -1004,7 +1004,7 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile,
// Assign aObject here so that it's available to recursive imports.
// See bug 384168.
*aObject = obj;
aObject.set(obj);
RootedScript tableScript(cx, script);
if (!tableScript) {
@ -1012,13 +1012,16 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile,
MOZ_ASSERT(tableScript);
}
*aTableScript = tableScript;
aTableScript.set(tableScript);
if (js::GetObjectJSClass(obj) == &kFakeBackstagePassJSClass) {
MOZ_ASSERT(mReuseLoaderGlobal);
// tableScript stays in the table until shutdown. To avoid it being
// collected and another script getting the same address, we root
// tableScript lower down in this function.
// tableScript stays in the table until shutdown. It is rooted by
// virtue of the fact that aTableScript is a handle to
// ModuleEntry::thisObjectKey, which is a PersistentRootedScript. Since
// ModuleEntries are never dynamically unloaded when mReuseLoaderGlobal
// is true, this prevents it from being collected and another script
// getting the same address.
mThisObjects.Put(tableScript, obj);
}
bool ok = false;
@ -1040,8 +1043,8 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile,
JS_GetPendingException(cx, aException);
JS_ClearPendingException(cx);
}
*aObject = nullptr;
*aTableScript = nullptr;
aObject.set(nullptr);
aTableScript.set(nullptr);
mThisObjects.Remove(tableScript);
return NS_ERROR_FAILURE;
}
@ -1049,14 +1052,12 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile,
/* Freed when we remove from the table. */
*aLocation = ToNewCString(nativePath);
if (!*aLocation) {
*aObject = nullptr;
*aTableScript = nullptr;
aObject.set(nullptr);
aTableScript.set(nullptr);
mThisObjects.Remove(tableScript);
return NS_ERROR_OUT_OF_MEMORY;
}
JS_AddNamedObjectRoot(cx, aObject, *aLocation);
JS_AddNamedScriptRoot(cx, aTableScript, *aLocation);
return NS_OK;
}
@ -1238,7 +1239,7 @@ mozJSComponentLoader::ImportInto(const nsACString &aLocation,
ModuleEntry* mod;
nsAutoPtr<ModuleEntry> newEntry;
if (!mImports.Get(key, &mod) && !mInProgressImports.Get(key, &mod)) {
newEntry = new ModuleEntry;
newEntry = new ModuleEntry(callercx);
if (!newEntry)
return NS_ERROR_OUT_OF_MEMORY;
mInProgressImports.Put(key, newEntry);

Просмотреть файл

@ -73,8 +73,8 @@ class mozJSComponentLoader : public mozilla::ModuleLoader,
nsresult ObjectForLocation(nsIFile* aComponentFile,
nsIURI *aComponent,
JSObject **aObject,
JSScript **aTableScript,
JS::MutableHandleObject aObject,
JS::MutableHandleScript aTableScript,
char **location,
bool aCatchException,
JS::MutableHandleValue aException);
@ -94,7 +94,9 @@ class mozJSComponentLoader : public mozilla::ModuleLoader,
class ModuleEntry : public mozilla::Module
{
public:
ModuleEntry() : mozilla::Module() {
ModuleEntry(JSContext* aCx)
: mozilla::Module(), obj(aCx, nullptr), thisObjectKey(aCx, nullptr)
{
mVersion = mozilla::Module::kVersion;
mCIDs = nullptr;
mContractIDs = nullptr;
@ -103,8 +105,6 @@ class mozJSComponentLoader : public mozilla::ModuleLoader,
loadProc = nullptr;
unloadProc = nullptr;
obj = nullptr;
thisObjectKey = nullptr;
location = nullptr;
}
@ -120,9 +120,8 @@ class mozJSComponentLoader : public mozilla::ModuleLoader,
JSAutoCompartment ac(cx, obj);
JS_SetAllNonReservedSlotsToUndefined(cx, obj);
JS_RemoveObjectRoot(cx, &obj);
if (thisObjectKey)
JS_RemoveScriptRoot(cx, &thisObjectKey);
obj = nullptr;
thisObjectKey = nullptr;
}
if (location)
@ -139,8 +138,8 @@ class mozJSComponentLoader : public mozilla::ModuleLoader,
const mozilla::Module::CIDEntry& entry);
nsCOMPtr<xpcIJSGetFactory> getfactoryobj;
JSObject *obj;
JSScript *thisObjectKey;
JS::PersistentRootedObject obj;
JS::PersistentRootedScript thisObjectKey;
char *location;
};

Просмотреть файл

@ -23,10 +23,6 @@ using mozilla::dom::DestroyProtoAndIfaceCache;
XPCJSContextStack::~XPCJSContextStack()
{
if (mSafeJSContext) {
{
JSAutoRequest ar(mSafeJSContext);
JS_RemoveObjectRoot(mSafeJSContext, &mSafeJSContextGlobal);
}
mSafeJSContextGlobal = nullptr;
JS_DestroyContextNoGC(mSafeJSContext);
mSafeJSContext = nullptr;
@ -187,7 +183,6 @@ XPCJSContextStack::InitSafeJSContext()
principal, options);
if (!mSafeJSContextGlobal)
MOZ_CRASH();
JS_AddNamedObjectRoot(mSafeJSContext, &mSafeJSContextGlobal, "SafeJSContext global");
// Note: make sure to set the private before calling
// InitClasses

Просмотреть файл

@ -3038,7 +3038,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
mWrappedJSRoots(nullptr),
mObjectHolderRoots(nullptr),
mWatchdogManager(new WatchdogManager(MOZ_THIS_IN_INITIALIZER_LIST())),
mJunkScope(nullptr),
mJunkScope(MOZ_THIS_IN_INITIALIZER_LIST()->Runtime(), nullptr),
mAsyncSnowWhiteFreer(new AsyncFreeSnowWhite())
{
DOM_InitInterfaces();
@ -3476,7 +3476,6 @@ XPCJSRuntime::GetJunkScope()
NS_ENSURE_SUCCESS(rv, nullptr);
mJunkScope = js::UncheckedUnwrap(&v.toObject());
JS_AddNamedObjectRoot(cx, &mJunkScope, "XPConnect Junk Compartment");
}
return mJunkScope;
}
@ -3484,10 +3483,5 @@ XPCJSRuntime::GetJunkScope()
void
XPCJSRuntime::DeleteJunkScope()
{
if(!mJunkScope)
return;
AutoSafeJSContext cx;
JS_RemoveObjectRoot(cx, &mJunkScope);
mJunkScope = nullptr;
}

Просмотреть файл

@ -650,18 +650,20 @@ File(JSContext *cx, unsigned argc, Value *vp)
return true;
}
static Value sScriptedInterruptCallback = UndefinedValue();
static Maybe<PersistentRootedValue> sScriptedInterruptCallback;
static bool
XPCShellInterruptCallback(JSContext *cx)
{
MOZ_ASSERT(!sScriptedInterruptCallback.empty());
RootedValue callback(cx, sScriptedInterruptCallback.ref());
// If no interrupt callback was set by script, no-op.
if (sScriptedInterruptCallback.isUndefined())
if (callback.isUndefined())
return true;
JSAutoCompartment ac(cx, &sScriptedInterruptCallback.toObject());
JSAutoCompartment ac(cx, &callback.toObject());
RootedValue rv(cx);
RootedValue callback(cx, sScriptedInterruptCallback);
if (!JS_CallFunctionValue(cx, JS::NullPtr(), callback, JS::HandleValueArray::empty(), &rv) ||
!rv.isBoolean())
{
@ -676,6 +678,8 @@ XPCShellInterruptCallback(JSContext *cx)
static bool
SetInterruptCallback(JSContext *cx, unsigned argc, jsval *vp)
{
MOZ_ASSERT(!sScriptedInterruptCallback.empty());
// Sanity-check args.
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
if (args.length() != 1) {
@ -685,7 +689,7 @@ SetInterruptCallback(JSContext *cx, unsigned argc, jsval *vp)
// Allow callers to remove the interrupt callback by passing undefined.
if (args[0].isUndefined()) {
sScriptedInterruptCallback = UndefinedValue();
sScriptedInterruptCallback.ref() = UndefinedValue();
return true;
}
@ -695,7 +699,7 @@ SetInterruptCallback(JSContext *cx, unsigned argc, jsval *vp)
return false;
}
sScriptedInterruptCallback = args[0];
sScriptedInterruptCallback.ref() = args[0];
return true;
}
@ -1471,6 +1475,7 @@ XRE_XPCShellMain(int argc, char **argv, char **envp)
// Override the default XPConnect interrupt callback. We could store the
// old one and restore it before shutting down, but there's not really a
// reason to bother.
sScriptedInterruptCallback.construct(rt, UndefinedValue());
JS_SetInterruptCallback(rt, XPCShellInterruptCallback);
cx = JS_NewContext(rt, 8192);
@ -1583,9 +1588,7 @@ XRE_XPCShellMain(int argc, char **argv, char **envp)
JS_DefineProperty(cx, glob, "__LOCATION__", JSVAL_VOID,
GetLocationProperty, nullptr, 0);
JS_AddValueRoot(cx, &sScriptedInterruptCallback);
result = ProcessArgs(cx, glob, argv, argc, &dirprovider);
JS_RemoveValueRoot(cx, &sScriptedInterruptCallback);
JS_DropPrincipals(rt, gJSPrincipals);
JS_SetAllNonReservedSlotsToUndefined(cx, glob);
@ -1603,6 +1606,8 @@ XRE_XPCShellMain(int argc, char **argv, char **envp)
rv = NS_ShutdownXPCOM( nullptr );
MOZ_ASSERT(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
sScriptedInterruptCallback.destroyIfConstructed();
#ifdef TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN
// test of late call and release (see above)
JSContext* bogusCX;

Просмотреть файл

@ -597,7 +597,7 @@ private:
nsTArray<xpcContextCallback> extraContextCallbacks;
nsRefPtr<WatchdogManager> mWatchdogManager;
JS::GCSliceCallback mPrevGCSliceCallback;
JSObject* mJunkScope;
JS::PersistentRootedObject mJunkScope;
nsRefPtr<AsyncFreeSnowWhite> mAsyncSnowWhiteFreer;
mozilla::TimeStamp mSlowScriptCheckpoint;
@ -2768,7 +2768,7 @@ public:
XPCJSContextStack(XPCJSRuntime *aRuntime)
: mRuntime(aRuntime)
, mSafeJSContext(nullptr)
, mSafeJSContextGlobal(nullptr)
, mSafeJSContextGlobal(aRuntime->Runtime(), nullptr)
{ }
virtual ~XPCJSContextStack();
@ -2804,7 +2804,7 @@ private:
AutoInfallibleTArray<XPCJSContextInfo, 16> mStack;
XPCJSRuntime* mRuntime;
JSContext* mSafeJSContext;
JSObject* mSafeJSContextGlobal;
JS::PersistentRootedObject mSafeJSContextGlobal;
};
/***************************************************************************/

Просмотреть файл

@ -12,9 +12,7 @@
NS_IMPL_ISUPPORTS2(ArrayBufferInputStream, nsIArrayBufferInputStream, nsIInputStream);
ArrayBufferInputStream::ArrayBufferInputStream()
: mRt(nullptr)
, mArrayBuffer(JSVAL_VOID)
, mBuffer(nullptr)
: mBuffer(nullptr)
, mBufferLength(0)
, mOffset(0)
, mPos(0)
@ -22,13 +20,6 @@ ArrayBufferInputStream::ArrayBufferInputStream()
{
}
ArrayBufferInputStream::~ArrayBufferInputStream()
{
if (mRt) {
JS_RemoveValueRootRT(mRt, &mArrayBuffer);
}
}
NS_IMETHODIMP
ArrayBufferInputStream::SetData(JS::Handle<JS::Value> aBuffer,
uint32_t aByteOffset,
@ -43,9 +34,7 @@ ArrayBufferInputStream::SetData(JS::Handle<JS::Value> aBuffer,
return NS_ERROR_FAILURE;
}
mRt = JS_GetRuntime(aCx);
mArrayBuffer = aBuffer;
JS_AddNamedValueRootRT(mRt, &mArrayBuffer, "mArrayBuffer");
mArrayBuffer.construct(aCx, aBuffer);
uint32_t buflen = JS_GetArrayBufferByteLength(arrayBuffer);
mOffset = std::min(buflen, aByteOffset);

Просмотреть файл

@ -8,10 +8,11 @@
#include "nsIArrayBufferInputStream.h"
#include "js/Value.h"
#include "mozilla/Maybe.h"
#define NS_ARRAYBUFFERINPUTSTREAM_CONTRACTID "@mozilla.org/io/arraybuffer-input-stream;1"
#define NS_ARRAYBUFFERINPUTSTREAM_CID \
{ /* 3014dde6-aa1c-41db-87d0-48764a3710f6 */ \
{ /* 3014dde6-aa1c-41db-87d0-48764a3710f6 */ \
0x3014dde6, \
0xaa1c, \
0x41db, \
@ -21,14 +22,13 @@
class ArrayBufferInputStream : public nsIArrayBufferInputStream {
public:
ArrayBufferInputStream();
virtual ~ArrayBufferInputStream();
virtual ~ArrayBufferInputStream() {}
NS_DECL_ISUPPORTS
NS_DECL_NSIARRAYBUFFERINPUTSTREAM
NS_DECL_NSIINPUTSTREAM
private:
JSRuntime* mRt;
jsval mArrayBuffer;
mozilla::Maybe<JS::PersistentRooted<JS::Value> > mArrayBuffer;
uint8_t* mBuffer; // start of actual buffer
uint32_t mBufferLength; // length of slice
uint32_t mOffset; // permanent offset from start of actual buffer