зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 04b06ee60ebf (bug 857648)
This commit is contained in:
Родитель
0715e0d433
Коммит
747409b970
|
@ -188,6 +188,69 @@ GetCurrentJSStack()
|
|||
|
||||
namespace exceptions {
|
||||
|
||||
class StackDescriptionOwner {
|
||||
public:
|
||||
StackDescriptionOwner(JS::StackDescription* aDescription)
|
||||
: mDescription(aDescription)
|
||||
{
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
|
||||
protected:
|
||||
~StackDescriptionOwner()
|
||||
{
|
||||
// Make sure to set mDescription to null before calling DropJSObjects, since
|
||||
// in debug builds DropJSObjects try to trace us and we don't want to trace
|
||||
// a dead StackDescription.
|
||||
if (mDescription) {
|
||||
JS::FreeStackDescription(nullptr, mDescription);
|
||||
mDescription = nullptr;
|
||||
}
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(StackDescriptionOwner)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(StackDescriptionOwner)
|
||||
|
||||
JS::FrameDescription& FrameAt(size_t aIndex)
|
||||
{
|
||||
MOZ_ASSERT(aIndex < mDescription->nframes);
|
||||
return mDescription->frames[aIndex];
|
||||
}
|
||||
|
||||
unsigned NumFrames()
|
||||
{
|
||||
return mDescription->nframes;
|
||||
}
|
||||
|
||||
private:
|
||||
JS::StackDescription* mDescription;
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(StackDescriptionOwner, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(StackDescriptionOwner, Release)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(StackDescriptionOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(StackDescriptionOwner)
|
||||
if (tmp->mDescription) {
|
||||
JS::FreeStackDescription(nullptr, tmp->mDescription);
|
||||
tmp->mDescription = nullptr;
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(StackDescriptionOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(StackDescriptionOwner)
|
||||
JS::StackDescription* desc = tmp->mDescription;
|
||||
if (tmp->mDescription) {
|
||||
for (size_t i = 0; i < desc->nframes; ++i) {
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDescription->frames[i].markedLocation1());
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDescription->frames[i].markedLocation2());
|
||||
}
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
class StackFrame : public nsIStackFrame
|
||||
{
|
||||
public:
|
||||
|
@ -221,10 +284,9 @@ protected:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual nsresult GetLineno(int32_t* aLineNo)
|
||||
virtual int32_t GetLineno()
|
||||
{
|
||||
*aLineNo = mLineno;
|
||||
return NS_OK;
|
||||
return mLineno;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStackFrame> mCaller;
|
||||
|
@ -264,11 +326,11 @@ class JSStackFrame : public StackFrame
|
|||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(JSStackFrame,
|
||||
StackFrame)
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(JSStackFrame, StackFrame)
|
||||
|
||||
// aStack must not be null.
|
||||
JSStackFrame(JS::Handle<JSObject*> aStack);
|
||||
// aStackDescription must not be null. aIndex must be a valid index
|
||||
// into aStackDescription.
|
||||
JSStackFrame(StackDescriptionOwner* aStackDescription, size_t aIndex);
|
||||
|
||||
static already_AddRefed<nsIStackFrame>
|
||||
CreateStack(JSContext* aCx, int32_t aMaxDepth = -1);
|
||||
|
@ -283,12 +345,13 @@ protected:
|
|||
return true;
|
||||
}
|
||||
|
||||
virtual nsresult GetLineno(int32_t* aLineNo) MOZ_OVERRIDE;
|
||||
virtual int32_t GetLineno() MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
virtual ~JSStackFrame();
|
||||
|
||||
JS::Heap<JSObject*> mStack;
|
||||
nsRefPtr<StackDescriptionOwner> mStackDescription;
|
||||
size_t mIndex;
|
||||
|
||||
bool mFilenameInitialized;
|
||||
bool mFunnameInitialized;
|
||||
|
@ -296,35 +359,26 @@ private:
|
|||
bool mCallerInitialized;
|
||||
};
|
||||
|
||||
JSStackFrame::JSStackFrame(JS::Handle<JSObject*> aStack)
|
||||
: mStack(aStack)
|
||||
JSStackFrame::JSStackFrame(StackDescriptionOwner* aStackDescription,
|
||||
size_t aIndex)
|
||||
: mStackDescription(aStackDescription)
|
||||
, mIndex(aIndex)
|
||||
, mFilenameInitialized(false)
|
||||
, mFunnameInitialized(false)
|
||||
, mLinenoInitialized(false)
|
||||
, mCallerInitialized(false)
|
||||
{
|
||||
MOZ_ASSERT(mStack);
|
||||
MOZ_ASSERT(aStackDescription && aIndex < aStackDescription->NumFrames());
|
||||
|
||||
mozilla::HoldJSObjects(this);
|
||||
mLineno = 0;
|
||||
mLanguage = nsIProgrammingLanguage::JAVASCRIPT;
|
||||
}
|
||||
|
||||
JSStackFrame::~JSStackFrame()
|
||||
{
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(JSStackFrame)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(JSStackFrame, StackFrame)
|
||||
tmp->mStack = nullptr;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(JSStackFrame, StackFrame)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(JSStackFrame, StackFrame)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mStack)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(JSStackFrame, StackFrame, mStackDescription)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(JSStackFrame, StackFrame)
|
||||
NS_IMPL_RELEASE_INHERITED(JSStackFrame, StackFrame)
|
||||
|
@ -356,20 +410,10 @@ NS_IMETHODIMP JSStackFrame::GetLanguageName(nsACString& aLanguageName)
|
|||
NS_IMETHODIMP JSStackFrame::GetFilename(nsAString& aFilename)
|
||||
{
|
||||
if (!mFilenameInitialized) {
|
||||
ThreadsafeAutoJSContext cx;
|
||||
JS::Rooted<JSObject*> stack(cx, mStack);
|
||||
JS::ExposeObjectToActiveJS(mStack);
|
||||
JSAutoCompartment ac(cx, stack);
|
||||
JS::Rooted<JS::Value> filenameVal(cx);
|
||||
if (!JS_GetProperty(cx, stack, "source", &filenameVal) ||
|
||||
!filenameVal.isString()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
JS::FrameDescription& desc = mStackDescription->FrameAt(mIndex);
|
||||
if (const char *filename = desc.filename()) {
|
||||
CopyUTF8toUTF16(filename, mFilename);
|
||||
}
|
||||
nsDependentJSString str;
|
||||
if (!str.init(cx, filenameVal.toString())) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mFilename = str;
|
||||
mFilenameInitialized = true;
|
||||
}
|
||||
|
||||
|
@ -392,22 +436,11 @@ NS_IMETHODIMP StackFrame::GetFilename(nsAString& aFilename)
|
|||
NS_IMETHODIMP JSStackFrame::GetName(nsAString& aFunction)
|
||||
{
|
||||
if (!mFunnameInitialized) {
|
||||
ThreadsafeAutoJSContext cx;
|
||||
JS::Rooted<JSObject*> stack(cx, mStack);
|
||||
JS::ExposeObjectToActiveJS(mStack);
|
||||
JSAutoCompartment ac(cx, stack);
|
||||
JS::Rooted<JS::Value> nameVal(cx);
|
||||
// functionDisplayName can be null
|
||||
if (!JS_GetProperty(cx, stack, "functionDisplayName", &nameVal) ||
|
||||
(!nameVal.isString() && !nameVal.isNull())) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
if (nameVal.isString()) {
|
||||
nsDependentJSString str;
|
||||
if (!str.init(cx, nameVal.toString())) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mFunname = str;
|
||||
JS::FrameDescription& desc = mStackDescription->FrameAt(mIndex);
|
||||
if (JSFlatString *name = desc.funDisplayName()) {
|
||||
mFunname.Assign(JS_GetFlatStringChars(name),
|
||||
// XXXbz Can't JS_GetStringLength on JSFlatString!
|
||||
JS_GetStringLength(JS_FORGET_STRING_FLATNESS(name)));
|
||||
}
|
||||
mFunnameInitialized = true;
|
||||
}
|
||||
|
@ -428,30 +461,23 @@ NS_IMETHODIMP StackFrame::GetName(nsAString& aFunction)
|
|||
}
|
||||
|
||||
// virtual
|
||||
nsresult
|
||||
JSStackFrame::GetLineno(int32_t* aLineNo)
|
||||
int32_t
|
||||
JSStackFrame::GetLineno()
|
||||
{
|
||||
if (!mLinenoInitialized) {
|
||||
ThreadsafeAutoJSContext cx;
|
||||
JS::Rooted<JSObject*> stack(cx, mStack);
|
||||
JS::ExposeObjectToActiveJS(mStack);
|
||||
JSAutoCompartment ac(cx, stack);
|
||||
JS::Rooted<JS::Value> lineVal(cx);
|
||||
if (!JS_GetProperty(cx, stack, "line", &lineVal) ||
|
||||
!lineVal.isNumber()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
mLineno = lineVal.toNumber();
|
||||
JS::FrameDescription& desc = mStackDescription->FrameAt(mIndex);
|
||||
mLineno = desc.lineno();
|
||||
mLinenoInitialized = true;
|
||||
}
|
||||
|
||||
return StackFrame::GetLineno(aLineNo);
|
||||
return StackFrame::GetLineno();
|
||||
}
|
||||
|
||||
/* readonly attribute int32_t lineNumber; */
|
||||
NS_IMETHODIMP StackFrame::GetLineNumber(int32_t* aLineNumber)
|
||||
{
|
||||
return GetLineno(aLineNumber);
|
||||
*aLineNumber = GetLineno();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute AUTF8String sourceLine; */
|
||||
|
@ -465,19 +491,8 @@ NS_IMETHODIMP StackFrame::GetSourceLine(nsACString& aSourceLine)
|
|||
NS_IMETHODIMP JSStackFrame::GetCaller(nsIStackFrame** aCaller)
|
||||
{
|
||||
if (!mCallerInitialized) {
|
||||
ThreadsafeAutoJSContext cx;
|
||||
JS::Rooted<JSObject*> stack(cx, mStack);
|
||||
JS::ExposeObjectToActiveJS(mStack);
|
||||
JSAutoCompartment ac(cx, stack);
|
||||
JS::Rooted<JS::Value> callerVal(cx);
|
||||
if (!JS_GetProperty(cx, stack, "parent", &callerVal) ||
|
||||
!callerVal.isObjectOrNull()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (callerVal.isObject()) {
|
||||
JS::Rooted<JSObject*> caller(cx, &callerVal.toObject());
|
||||
mCaller = new JSStackFrame(caller);
|
||||
if (mIndex + 1 < mStackDescription->NumFrames()) {
|
||||
mCaller = new JSStackFrame(mStackDescription, mIndex+1);
|
||||
} else {
|
||||
// Do we really need this dummy frame? If so, we should document why... I
|
||||
// guess for symmetry with the "nothing on the stack" case, which returns
|
||||
|
@ -517,16 +532,11 @@ NS_IMETHODIMP StackFrame::ToString(nsACString& _retval)
|
|||
if (funname.IsEmpty()) {
|
||||
funname.AssignLiteral("<TOP_LEVEL>");
|
||||
}
|
||||
|
||||
int32_t lineno;
|
||||
rv = GetLineno(&lineno);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
static const char format[] = "%s frame :: %s :: %s :: line %d";
|
||||
_retval.AppendPrintf(format, frametype,
|
||||
NS_ConvertUTF16toUTF8(filename).get(),
|
||||
NS_ConvertUTF16toUTF8(funname).get(),
|
||||
lineno);
|
||||
GetLineno());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -538,16 +548,17 @@ JSStackFrame::CreateStack(JSContext* aCx, int32_t aMaxDepth)
|
|||
aMaxDepth = MAX_FRAMES;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> stack(aCx);
|
||||
if (!JS::CaptureCurrentStack(aCx, &stack, aMaxDepth)) {
|
||||
JS::StackDescription* desc = JS::DescribeStack(aCx, aMaxDepth);
|
||||
if (!desc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStackFrame> first;
|
||||
if (!stack) {
|
||||
if (desc->nframes == 0) {
|
||||
first = new StackFrame();
|
||||
} else {
|
||||
first = new JSStackFrame(stack);
|
||||
nsRefPtr<StackDescriptionOwner> descOwner = new StackDescriptionOwner(desc);
|
||||
first = new JSStackFrame(descOwner, 0);
|
||||
}
|
||||
return first.forget();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче