Bug 963895. Add threadsafe versions of AutoJSContext/AutoSafeJSContext. r=bholley

This commit is contained in:
Boris Zbarsky 2014-01-29 22:33:03 -08:00
parent e31f8a4e76
commit 30b2700eab
4 changed files with 79 additions and 6 deletions

View File

@ -378,10 +378,7 @@ NS_IMETHODIMP JSStackFrame::GetFilename(nsACString& aFilename)
if (!mFilenameInitialized) {
JS::FrameDescription& desc = mStackDescription->FrameAt(mIndex);
if (desc.script()) {
// This cx dance is silly, since JS_GetScriptFilename ignores
// its cx argument.
JSContext* cx = nsContentUtils::GetDefaultJSContextForThread();
JSAutoRequest ar(cx);
ThreadsafeAutoSafeJSContext cx;
JSAutoCompartment ac(cx, desc.script());
const char* filename = JS_GetScriptFilename(cx, desc.script());
if (filename) {
@ -407,8 +404,7 @@ NS_IMETHODIMP JSStackFrame::GetName(nsACString& aFunction)
if (!mFunnameInitialized) {
JS::FrameDescription& desc = mStackDescription->FrameAt(mIndex);
if (desc.fun() && desc.script()) {
JSContext* cx = nsContentUtils::GetDefaultJSContextForThread();
JSAutoRequest ar(cx);
ThreadsafeAutoSafeJSContext cx;
JSAutoCompartment ac(cx, desc.script());
JS::Rooted<JSFunction*> fun(cx, desc.fun());
JS::Rooted<JSString*> funid(cx, JS_GetFunctionDisplayId(fun));

View File

@ -91,6 +91,7 @@ LOCAL_INCLUDES += [
'/content/svg/content/src',
'/dom/base',
'/dom/events',
'/dom/workers',
'/js/ipc',
'/layout/base',
'/layout/style',

View File

@ -10,6 +10,7 @@
#include "mozilla/dom/EventTarget.h"
#include "nsDOMJSUtils.h"
#include "xpcprivate.h"
#include "WorkerPrivate.h"
using mozilla::dom::EventTarget;
using mozilla::DebugOnly;
@ -198,11 +199,55 @@ AutoJSContext::operator JSContext*() const
return mCx;
}
ThreadsafeAutoJSContext::ThreadsafeAutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
if (NS_IsMainThread()) {
mCx = nullptr;
mAutoJSContext.construct();
} else {
mCx = mozilla::dom::workers::GetCurrentThreadJSContext();
mRequest.construct(mCx);
}
}
ThreadsafeAutoJSContext::operator JSContext*() const
{
if (mCx) {
return mCx;
} else {
return mAutoJSContext.ref();
}
}
AutoSafeJSContext::AutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
: AutoJSContext(true MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
{
}
ThreadsafeAutoSafeJSContext::ThreadsafeAutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
if (NS_IsMainThread()) {
mCx = nullptr;
mAutoSafeJSContext.construct();
} else {
mCx = mozilla::dom::workers::GetCurrentThreadJSContext();
mRequest.construct(mCx);
}
}
ThreadsafeAutoSafeJSContext::operator JSContext*() const
{
if (mCx) {
return mCx;
} else {
return mAutoSafeJSContext.ref();
}
}
AutoPushJSContext::AutoPushJSContext(JSContext *aCx) : mCx(aCx)
{
if (mCx && mCx != nsXPConnect::XPConnect()->GetCurrentJSContext()) {

View File

@ -114,6 +114,22 @@ private:
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
/**
* Use ThreadsafeAutoJSContext when you want an AutoJSContext but might be
* running on a worker thread.
*/
class MOZ_STACK_CLASS ThreadsafeAutoJSContext {
public:
ThreadsafeAutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
operator JSContext*() const;
private:
JSContext* mCx; // Used on workers. Null means mainthread.
Maybe<JSAutoRequest> mRequest; // Used on workers.
Maybe<AutoJSContext> mAutoJSContext; // Used on main thread.
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
/**
* AutoSafeJSContext is similar to AutoJSContext but will only return the safe
* JS context. That means it will never call ::GetCurrentJSContext().
@ -123,6 +139,21 @@ public:
AutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
};
/**
* Like AutoSafeJSContext but can be used safely on worker threads.
*/
class MOZ_STACK_CLASS ThreadsafeAutoSafeJSContext {
public:
ThreadsafeAutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
operator JSContext*() const;
private:
JSContext* mCx; // Used on workers. Null means mainthread.
Maybe<JSAutoRequest> mRequest; // Used on workers.
Maybe<AutoSafeJSContext> mAutoSafeJSContext; // Used on main thread.
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
/**
* Use AutoPushJSContext when you want to use a specific JSContext that may or
* may not be already on the stack. This differs from nsCxPusher in that it only