зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 6e043a8ce335 (bug 996060) for cgc test failure in testCall.js. r=backout
This commit is contained in:
Родитель
14189e51f1
Коммит
bcf24386ee
|
@ -4,8 +4,6 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "mozilla/ScopeExit.h"
|
|
||||||
|
|
||||||
#include "jscompartment.h"
|
#include "jscompartment.h"
|
||||||
#include "jsfriendapi.h"
|
#include "jsfriendapi.h"
|
||||||
#include "jsstr.h"
|
#include "jsstr.h"
|
||||||
|
@ -204,100 +202,3 @@ BEGIN_TEST(testSavedStacks_selfHostedFrames)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
END_TEST(testSavedStacks_selfHostedFrames)
|
END_TEST(testSavedStacks_selfHostedFrames)
|
||||||
|
|
||||||
BEGIN_TEST(test_JS_GetPendingExceptionStack)
|
|
||||||
{
|
|
||||||
CHECK(js::DefineTestingFunctions(cx, global, false, false));
|
|
||||||
|
|
||||||
const char* sourceText =
|
|
||||||
// 1 2 3
|
|
||||||
// 123456789012345678901234567890123456789
|
|
||||||
"(function one() { \n" // 1
|
|
||||||
" (function two() { \n" // 2
|
|
||||||
" (function three() { \n" // 3
|
|
||||||
" throw 5; \n" // 4
|
|
||||||
" }()); \n" // 5
|
|
||||||
" }()); \n" // 6
|
|
||||||
"}()) \n"; // 7
|
|
||||||
|
|
||||||
JS::RootedValue val(cx);
|
|
||||||
JS::CompileOptions opts(cx);
|
|
||||||
opts.setFileAndLine("filename.js", 1U);
|
|
||||||
JS::ContextOptionsRef(cx).setDontReportUncaught(true);
|
|
||||||
JSContext* context = cx;
|
|
||||||
auto resetReportUncaught = mozilla::MakeScopeExit([=]() {
|
|
||||||
JS::ContextOptionsRef(context).setDontReportUncaught(false);
|
|
||||||
});
|
|
||||||
bool ok = JS::Evaluate(cx, opts, sourceText, strlen(sourceText), &val);
|
|
||||||
|
|
||||||
CHECK(!ok);
|
|
||||||
CHECK(JS_IsExceptionPending(cx));
|
|
||||||
CHECK(val.isUndefined());
|
|
||||||
|
|
||||||
JS::RootedObject stack(cx);
|
|
||||||
CHECK(JS::GetPendingExceptionStack(cx, &stack));
|
|
||||||
CHECK(stack);
|
|
||||||
CHECK(stack->is<js::SavedFrame>());
|
|
||||||
JS::Rooted<js::SavedFrame*> savedFrameStack(cx, &stack->as<SavedFrame>());
|
|
||||||
|
|
||||||
JS_GetPendingException(cx, &val);
|
|
||||||
CHECK(val.isInt32());
|
|
||||||
CHECK(val.toInt32() == 5);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
uint32_t line;
|
|
||||||
uint32_t column;
|
|
||||||
const char* source;
|
|
||||||
const char* functionDisplayName;
|
|
||||||
} expected[] = {
|
|
||||||
{ 4, 7, "filename.js", "three" },
|
|
||||||
{ 3, 15, "filename.js", "two" },
|
|
||||||
{ 2, 13, "filename.js", "one" },
|
|
||||||
{ 1, 11, "filename.js", nullptr }
|
|
||||||
};
|
|
||||||
|
|
||||||
size_t i = 0;
|
|
||||||
for (JS::Handle<js::SavedFrame*> frame : js::SavedFrame::RootedRange(cx, savedFrameStack)) {
|
|
||||||
CHECK(i < 4);
|
|
||||||
|
|
||||||
// Line
|
|
||||||
uint32_t line = 123;
|
|
||||||
JS::SavedFrameResult result = JS::GetSavedFrameLine(cx, frame, &line,
|
|
||||||
JS::SavedFrameSelfHosted::Exclude);
|
|
||||||
CHECK(result == JS::SavedFrameResult::Ok);
|
|
||||||
CHECK_EQUAL(line, expected[i].line);
|
|
||||||
|
|
||||||
// Column
|
|
||||||
uint32_t column = 123;
|
|
||||||
result = JS::GetSavedFrameColumn(cx, frame, &column,
|
|
||||||
JS::SavedFrameSelfHosted::Exclude);
|
|
||||||
CHECK(result == JS::SavedFrameResult::Ok);
|
|
||||||
CHECK_EQUAL(column, expected[i].column);
|
|
||||||
|
|
||||||
// Source
|
|
||||||
JS::RootedString str(cx);
|
|
||||||
result = JS::GetSavedFrameSource(cx, frame, &str, JS::SavedFrameSelfHosted::Exclude);
|
|
||||||
CHECK(result == JS::SavedFrameResult::Ok);
|
|
||||||
JSLinearString* linear = str->ensureLinear(cx);
|
|
||||||
CHECK(linear);
|
|
||||||
CHECK(js::StringEqualsAscii(linear, expected[i].source));
|
|
||||||
|
|
||||||
// Function display name
|
|
||||||
result = JS::GetSavedFrameFunctionDisplayName(cx, frame, &str,
|
|
||||||
JS::SavedFrameSelfHosted::Exclude);
|
|
||||||
CHECK(result == JS::SavedFrameResult::Ok);
|
|
||||||
if (auto expectedName = expected[i].functionDisplayName) {
|
|
||||||
CHECK(str);
|
|
||||||
linear = str->ensureLinear(cx);
|
|
||||||
CHECK(linear);
|
|
||||||
CHECK(js::StringEqualsAscii(linear, expectedName));
|
|
||||||
} else {
|
|
||||||
CHECK(!str);
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
END_TEST(test_JS_GetPendingExceptionStack)
|
|
||||||
|
|
|
@ -5994,12 +5994,12 @@ JS_GetPendingException(JSContext* cx, MutableHandleValue vp)
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
JS_PUBLIC_API(void)
|
||||||
JS_SetPendingException(JSContext* cx, HandleValue value, JS::ExceptionStackBehavior behavior)
|
JS_SetPendingException(JSContext* cx, HandleValue value)
|
||||||
{
|
{
|
||||||
AssertHeapIsIdle(cx);
|
AssertHeapIsIdle(cx);
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
assertSameCompartment(cx, value);
|
assertSameCompartment(cx, value);
|
||||||
cx->setPendingException(value, behavior);
|
cx->setPendingException(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
JS_PUBLIC_API(void)
|
||||||
|
@ -6702,11 +6702,3 @@ JS::GCThingTraceKind(void* thing)
|
||||||
MOZ_ASSERT(thing);
|
MOZ_ASSERT(thing);
|
||||||
return static_cast<js::gc::Cell*>(thing)->getTraceKind();
|
return static_cast<js::gc::Cell*>(thing)->getTraceKind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
|
||||||
JS::GetPendingExceptionStack(JSContext* cx, JS::MutableHandleObject stackp)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(cx);
|
|
||||||
return cx->getPendingExceptionStack(stackp);
|
|
||||||
}
|
|
||||||
|
|
|
@ -5463,18 +5463,6 @@ JS_GetRegExpSource(JSContext* cx, JS::HandleObject obj);
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
namespace JS {
|
|
||||||
|
|
||||||
enum class ExceptionStackBehavior: bool {
|
|
||||||
// Capture the current JS stack when setting the exception. It may be
|
|
||||||
// retrieved by JS::GetPendingExceptionStack.
|
|
||||||
Capture,
|
|
||||||
// Do not capture any stack.
|
|
||||||
DoNotCapture
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace JS
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(bool)
|
extern JS_PUBLIC_API(bool)
|
||||||
JS_IsExceptionPending(JSContext* cx);
|
JS_IsExceptionPending(JSContext* cx);
|
||||||
|
|
||||||
|
@ -5482,8 +5470,7 @@ extern JS_PUBLIC_API(bool)
|
||||||
JS_GetPendingException(JSContext* cx, JS::MutableHandleValue vp);
|
JS_GetPendingException(JSContext* cx, JS::MutableHandleValue vp);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void)
|
extern JS_PUBLIC_API(void)
|
||||||
JS_SetPendingException(JSContext* cx, JS::HandleValue v,
|
JS_SetPendingException(JSContext* cx, JS::HandleValue v);
|
||||||
JS::ExceptionStackBehavior behavior = JS::ExceptionStackBehavior::Capture);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void)
|
extern JS_PUBLIC_API(void)
|
||||||
JS_ClearPendingException(JSContext* cx);
|
JS_ClearPendingException(JSContext* cx);
|
||||||
|
@ -5993,32 +5980,6 @@ SetOutOfMemoryCallback(JSRuntime* rt, OutOfMemoryCallback cb, void* data);
|
||||||
extern JS_PUBLIC_API(bool)
|
extern JS_PUBLIC_API(bool)
|
||||||
CaptureCurrentStack(JSContext* cx, MutableHandleObject stackp, unsigned maxFrameCount = 0);
|
CaptureCurrentStack(JSContext* cx, MutableHandleObject stackp, unsigned maxFrameCount = 0);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the `SavedFrame` stack object captured when the pending exception was set
|
|
||||||
* on the `JSContext`. This will correspond to a 'throw' statement in JS, or the
|
|
||||||
* state at which `JS_SetPendingException` is called by VM code or a JSAPI
|
|
||||||
* consumer.
|
|
||||||
*
|
|
||||||
* This is not the same stack as `e.stack` when `e` is an `Error` object. (That
|
|
||||||
* would be `JS::ExceptionStackOrNull`). That stack is the stack when the
|
|
||||||
* `Error` object was created, which could be much earlier than when it is
|
|
||||||
* thrown.
|
|
||||||
*
|
|
||||||
* Note that it is possible that `stackp` is null with a `true` return value
|
|
||||||
* when any of the following situations:
|
|
||||||
* - There is no pending exception (and hence no stack for the pending
|
|
||||||
* exception).
|
|
||||||
* - The exception was set on the `cx` when there was no JS on
|
|
||||||
* the stack (and therefore the stack is correctly empty).
|
|
||||||
* - The exception being thrown is an out of memory exception.
|
|
||||||
* a stack via `JS::ExceptionStackBehavior::DoNotCapture`.
|
|
||||||
*
|
|
||||||
* If `stackp` is non-null after this call, it is guaranteed to be in the same
|
|
||||||
* compartment that `cx` is in.
|
|
||||||
*/
|
|
||||||
extern JS_PUBLIC_API(MOZ_MUST_USE bool)
|
|
||||||
GetPendingExceptionStack(JSContext* cx, MutableHandleObject stackp);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a utility function for preparing an async stack to be used
|
* This is a utility function for preparing an async stack to be used
|
||||||
* by some other object. This may be used when you need to treat a
|
* by some other object. This may be used when you need to treat a
|
||||||
|
|
|
@ -302,8 +302,7 @@ js::ReportOutOfMemory(ExclusiveContext* cxArg)
|
||||||
oomCallback(cx, cx->runtime()->oomCallbackData);
|
oomCallback(cx, cx->runtime()->oomCallbackData);
|
||||||
|
|
||||||
if (cx->options().autoJSAPIOwnsErrorReporting() || JS_IsRunning(cx)) {
|
if (cx->options().autoJSAPIOwnsErrorReporting() || JS_IsRunning(cx)) {
|
||||||
RootedValue v(cx, StringValue(cx->names().outOfMemory));
|
cx->setPendingException(StringValue(cx->names().outOfMemory));
|
||||||
cx->setPendingException(v);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -962,7 +961,6 @@ JSContext::JSContext(JSRuntime* rt)
|
||||||
: ExclusiveContext(rt, &rt->mainThread, Context_JS),
|
: ExclusiveContext(rt, &rt->mainThread, Context_JS),
|
||||||
throwing(false),
|
throwing(false),
|
||||||
unwrappedException_(this),
|
unwrappedException_(this),
|
||||||
unwrappedPendingExceptionStack_(this),
|
|
||||||
options_(),
|
options_(),
|
||||||
overRecursed_(false),
|
overRecursed_(false),
|
||||||
propagatingForcedReturn_(false),
|
propagatingForcedReturn_(false),
|
||||||
|
@ -999,28 +997,11 @@ JSContext::getPendingException(MutableHandleValue rval)
|
||||||
if (!compartment()->wrap(this, rval))
|
if (!compartment()->wrap(this, rval))
|
||||||
return false;
|
return false;
|
||||||
assertSameCompartment(this, rval);
|
assertSameCompartment(this, rval);
|
||||||
setPendingException(rval, JS::ExceptionStackBehavior::DoNotCapture);
|
setPendingException(rval);
|
||||||
overRecursed_ = wasOverRecursed;
|
overRecursed_ = wasOverRecursed;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
JSContext::getPendingExceptionStack(MutableHandleObject stackp)
|
|
||||||
{
|
|
||||||
if (!unwrappedPendingExceptionStack_) {
|
|
||||||
stackp.set(nullptr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
stackp.set(unwrappedPendingExceptionStack_);
|
|
||||||
if (!compartment()->wrap(this, stackp)) {
|
|
||||||
stackp.set(nullptr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JSContext::isThrowingOutOfMemory()
|
JSContext::isThrowingOutOfMemory()
|
||||||
{
|
{
|
||||||
|
|
|
@ -317,12 +317,6 @@ struct JSContext : public js::ExclusiveContext,
|
||||||
/* Exception state -- the exception member is a GC root by definition. */
|
/* Exception state -- the exception member is a GC root by definition. */
|
||||||
bool throwing; /* is there a pending exception? */
|
bool throwing; /* is there a pending exception? */
|
||||||
JS::PersistentRooted<JS::Value> unwrappedException_; /* most-recently-thrown exception */
|
JS::PersistentRooted<JS::Value> unwrappedException_; /* most-recently-thrown exception */
|
||||||
/*
|
|
||||||
* The SavedFrame stack captured when we set a pending exception, and
|
|
||||||
* cleared out when we clear pending exceptions.
|
|
||||||
*/
|
|
||||||
JS::PersistentRooted<js::SavedFrame*> unwrappedPendingExceptionStack_;
|
|
||||||
|
|
||||||
|
|
||||||
/* Per-context options. */
|
/* Per-context options. */
|
||||||
JS::ContextOptions options_;
|
JS::ContextOptions options_;
|
||||||
|
@ -444,22 +438,17 @@ struct JSContext : public js::ExclusiveContext,
|
||||||
|
|
||||||
MOZ_MUST_USE
|
MOZ_MUST_USE
|
||||||
bool getPendingException(JS::MutableHandleValue rval);
|
bool getPendingException(JS::MutableHandleValue rval);
|
||||||
MOZ_MUST_USE
|
|
||||||
bool getPendingExceptionStack(JS::MutableHandleObject stackp);
|
|
||||||
|
|
||||||
bool isThrowingOutOfMemory();
|
bool isThrowingOutOfMemory();
|
||||||
bool isThrowingDebuggeeWouldRun();
|
bool isThrowingDebuggeeWouldRun();
|
||||||
bool isClosingGenerator();
|
bool isClosingGenerator();
|
||||||
|
|
||||||
void setPendingException(
|
void setPendingException(js::Value v);
|
||||||
js::HandleValue v,
|
|
||||||
JS::ExceptionStackBehavior behavior = JS::ExceptionStackBehavior::Capture);
|
|
||||||
|
|
||||||
void clearPendingException() {
|
void clearPendingException() {
|
||||||
throwing = false;
|
throwing = false;
|
||||||
overRecursed_ = false;
|
overRecursed_ = false;
|
||||||
unwrappedException_.setUndefined();
|
unwrappedException_.setUndefined();
|
||||||
unwrappedPendingExceptionStack_ = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isThrowingOverRecursed() const { return throwing && overRecursed_; }
|
bool isThrowingOverRecursed() const { return throwing && overRecursed_; }
|
||||||
|
|
|
@ -365,18 +365,8 @@ ExclusiveContext::typeLifoAlloc()
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
JSContext::setPendingException(js::HandleValue v, JS::ExceptionStackBehavior behavior)
|
JSContext::setPendingException(js::Value v)
|
||||||
{
|
{
|
||||||
if (behavior == JS::ExceptionStackBehavior::Capture &&
|
|
||||||
compartment() &&
|
|
||||||
v != StringValue(names().outOfMemory))
|
|
||||||
{
|
|
||||||
js::RootedSavedFrame stack(this);
|
|
||||||
if (!compartment()->savedStacks().saveCurrentStack(this, &stack))
|
|
||||||
clearPendingException();
|
|
||||||
unwrappedPendingExceptionStack_ = stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
// overRecursed_ is set after the fact by ReportOverRecursed.
|
// overRecursed_ is set after the fact by ReportOverRecursed.
|
||||||
this->overRecursed_ = false;
|
this->overRecursed_ = false;
|
||||||
this->throwing = true;
|
this->throwing = true;
|
||||||
|
|
|
@ -678,7 +678,7 @@ js::ReportUncaughtException(JSContext* cx)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cx->setPendingException(exn, JS::ExceptionStackBehavior::DoNotCapture);
|
cx->setPendingException(exn);
|
||||||
CallErrorReporter(cx, err.message(), err.report());
|
CallErrorReporter(cx, err.message(), err.report());
|
||||||
cx->clearPendingException();
|
cx->clearPendingException();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -975,10 +975,8 @@ js::ThrowStopIteration(JSContext* cx)
|
||||||
// StopIteration isn't a constructor, but it's stored in GlobalObject
|
// StopIteration isn't a constructor, but it's stored in GlobalObject
|
||||||
// as one, out of laziness. Hence the GetBuiltinConstructor call here.
|
// as one, out of laziness. Hence the GetBuiltinConstructor call here.
|
||||||
RootedObject ctor(cx);
|
RootedObject ctor(cx);
|
||||||
if (GetBuiltinConstructor(cx, JSProto_StopIteration, &ctor)) {
|
if (GetBuiltinConstructor(cx, JSProto_StopIteration, &ctor))
|
||||||
RootedValue v(cx, ObjectValue(*ctor));
|
cx->setPendingException(ObjectValue(*ctor));
|
||||||
cx->setPendingException(v);
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1252,7 +1250,7 @@ js::UnwindIteratorForException(JSContext* cx, HandleObject obj)
|
||||||
return false;
|
return false;
|
||||||
if (!getOk)
|
if (!getOk)
|
||||||
return false;
|
return false;
|
||||||
cx->setPendingException(v, JS::ExceptionStackBehavior::DoNotCapture);
|
cx->setPendingException(v);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -410,10 +410,8 @@ ErrorCopier::~ErrorCopier()
|
||||||
ac.reset();
|
ac.reset();
|
||||||
Rooted<ErrorObject*> errObj(cx, &exc.toObject().as<ErrorObject>());
|
Rooted<ErrorObject*> errObj(cx, &exc.toObject().as<ErrorObject>());
|
||||||
JSObject* copyobj = CopyErrorObject(cx, errObj);
|
JSObject* copyobj = CopyErrorObject(cx, errObj);
|
||||||
if (copyobj) {
|
if (copyobj)
|
||||||
RootedValue v(cx, ObjectValue(*copyobj));
|
cx->setPendingException(ObjectValue(*copyobj));
|
||||||
cx->setPendingException(v, JS::ExceptionStackBehavior::DoNotCapture);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,8 +137,7 @@ js::GeneratorThrowOrClose(JSContext* cx, AbstractFramePtr frame, Handle<Generato
|
||||||
MOZ_ASSERT(arg.isUndefined());
|
MOZ_ASSERT(arg.isUndefined());
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedValue v(cx, MagicValue(JS_GENERATOR_CLOSING));
|
cx->setPendingException(MagicValue(JS_GENERATOR_CLOSING));
|
||||||
cx->setPendingException(v);
|
|
||||||
genObj->setClosing();
|
genObj->setClosing();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -3634,8 +3634,7 @@ CASE(JSOP_RETSUB)
|
||||||
* be necessary, but it seems clearer. And it points out a FIXME:
|
* be necessary, but it seems clearer. And it points out a FIXME:
|
||||||
* 350509, due to Igor Bukanov.
|
* 350509, due to Igor Bukanov.
|
||||||
*/
|
*/
|
||||||
ReservedRooted<Value> v(&rootValue0, rval);
|
cx->setPendingException(rval);
|
||||||
cx->setPendingException(v);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(rval.isInt32());
|
MOZ_ASSERT(rval.isInt32());
|
||||||
|
|
Загрузка…
Ссылка в новой задаче