author | Jason Orendorff <jorendorff@mozilla.com> |
Mon, 05 Mar 2018 12:59:09 -0600 | |
changeset 462581 | d60b465bf9e32d7fb2e644cc4f709f99ff99fd17 |
parent 462580 | 1a7cb8857de44f7f0bdf665c07fbc2097bf93e93 |
child 462582 | 7a7c97827b69caf3535cdec96729cf42f2e1b078 |
push id | 9165 |
push user | asasaki@mozilla.com |
push date | Thu, 26 Apr 2018 21:04:54 +0000 |
treeherder | mozilla-beta@064c3804de2e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jimb |
bugs | 1443583 |
milestone | 61.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/jit/JitFrames.cpp +++ b/js/src/jit/JitFrames.cpp @@ -493,34 +493,34 @@ HandleExceptionBaseline(JSContext* cx, c ForcedReturn(cx, frame, pc, rfe); return; } again: if (cx->isExceptionPending()) { if (!cx->isClosingGenerator()) { switch (Debugger::onExceptionUnwind(cx, frame.baselineFrame())) { - case JSTRAP_ERROR: + case ResumeMode::Terminate: // Uncatchable exception. MOZ_ASSERT(!cx->isExceptionPending()); goto again; - case JSTRAP_CONTINUE: - case JSTRAP_THROW: + case ResumeMode::Continue: + case ResumeMode::Throw: MOZ_ASSERT(cx->isExceptionPending()); break; - case JSTRAP_RETURN: + case ResumeMode::Return: if (script->hasTrynotes()) CloseLiveIteratorsBaselineForUncatchableException(cx, frame, pc); ForcedReturn(cx, frame, pc, rfe); return; default: - MOZ_CRASH("Invalid trap status"); + MOZ_CRASH("Invalid onExceptionUnwind resume mode"); } } if (script->hasTrynotes()) { EnvironmentIter ei(cx, frame.baselineFrame(), pc); if (!ProcessTryNotesBaseline(cx, frame, ei, rfe, &pc)) goto again; if (rfe->kind != ResumeFromException::RESUME_ENTRY_FRAME) {
--- a/js/src/jit/VMFunctions.cpp +++ b/js/src/jit/VMFunctions.cpp @@ -817,32 +817,32 @@ WrapObjectPure(JSContext* cx, JSObject* } bool DebugPrologue(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool* mustReturn) { *mustReturn = false; switch (Debugger::onEnterFrame(cx, frame)) { - case JSTRAP_CONTINUE: + case ResumeMode::Continue: return true; - case JSTRAP_RETURN: + case ResumeMode::Return: // The script is going to return immediately, so we have to call the // debug epilogue handler as well. MOZ_ASSERT(frame->hasReturnValue()); *mustReturn = true; return jit::DebugEpilogue(cx, frame, pc, true); - case JSTRAP_THROW: - case JSTRAP_ERROR: + case ResumeMode::Throw: + case ResumeMode::Terminate: return false; default: - MOZ_CRASH("bad Debugger::onEnterFrame status"); + MOZ_CRASH("bad Debugger::onEnterFrame resume mode"); } } bool DebugEpilogueOnBaselineReturn(JSContext* cx, BaselineFrame* frame, jsbytecode* pc) { if (!DebugEpilogue(cx, frame, pc, true)) { // DebugEpilogue popped the frame by updating packedExitFP, so run the @@ -1092,68 +1092,66 @@ HandleDebugTrap(JSContext* cx, BaselineF if (!DebugAfterYield(cx, frame)) return false; } MOZ_ASSERT(frame->isDebuggee()); MOZ_ASSERT(script->stepModeEnabled() || script->hasBreakpointsAt(pc)); RootedValue rval(cx); - JSTrapStatus status = JSTRAP_CONTINUE; + ResumeMode resumeMode = ResumeMode::Continue; if (script->stepModeEnabled()) - status = Debugger::onSingleStep(cx, &rval); + resumeMode = Debugger::onSingleStep(cx, &rval); - if (status == JSTRAP_CONTINUE && script->hasBreakpointsAt(pc)) - status = Debugger::onTrap(cx, &rval); + if (resumeMode == ResumeMode::Continue && script->hasBreakpointsAt(pc)) + resumeMode = Debugger::onTrap(cx, &rval); - switch (status) { - case JSTRAP_CONTINUE: + switch (resumeMode) { + case ResumeMode::Continue: break; - case JSTRAP_ERROR: + case ResumeMode::Terminate: return false; - case JSTRAP_RETURN: + case ResumeMode::Return: *mustReturn = true; frame->setReturnValue(rval); return jit::DebugEpilogue(cx, frame, pc, true); - case JSTRAP_THROW: + case ResumeMode::Throw: cx->setPendingException(rval); return false; default: - MOZ_CRASH("Invalid trap status"); + MOZ_CRASH("Invalid step/breakpoint resume mode"); } return true; } bool OnDebuggerStatement(JSContext* cx, BaselineFrame* frame, jsbytecode* pc, bool* mustReturn) { *mustReturn = false; switch (Debugger::onDebuggerStatement(cx, frame)) { - case JSTRAP_ERROR: - return false; - - case JSTRAP_CONTINUE: + case ResumeMode::Continue: return true; - case JSTRAP_RETURN: + case ResumeMode::Return: *mustReturn = true; return jit::DebugEpilogue(cx, frame, pc, true); - case JSTRAP_THROW: + case ResumeMode::Throw: + case ResumeMode::Terminate: return false; default: - MOZ_CRASH("Invalid trap status"); + MOZ_CRASH("Invalid OnDebuggerStatement resume mode"); } } bool GlobalHasLiveOnDebuggerStatement(JSContext* cx) { AutoUnsafeCallWithABI unsafe; return cx->compartment()->isDebuggee() &&
--- a/js/src/vm/Debugger-inl.h +++ b/js/src/vm/Debugger-inl.h @@ -36,38 +36,38 @@ js::Debugger::fromJSObject(const JSObjec /* static */ inline bool js::Debugger::checkNoExecute(JSContext* cx, HandleScript script) { if (!cx->compartment()->isDebuggee() || !cx->noExecuteDebuggerTop) return true; return slowPathCheckNoExecute(cx, script); } -/* static */ JSTrapStatus +/* static */ js::ResumeMode js::Debugger::onEnterFrame(JSContext* cx, AbstractFramePtr frame) { MOZ_ASSERT_IF(frame.hasScript() && frame.script()->isDebuggee(), frame.isDebuggee()); if (!frame.isDebuggee()) - return JSTRAP_CONTINUE; + return ResumeMode::Continue; return slowPathOnEnterFrame(cx, frame); } -/* static */ JSTrapStatus +/* static */ js::ResumeMode js::Debugger::onDebuggerStatement(JSContext* cx, AbstractFramePtr frame) { if (!cx->compartment()->isDebuggee()) - return JSTRAP_CONTINUE; + return ResumeMode::Continue; return slowPathOnDebuggerStatement(cx, frame); } -/* static */ JSTrapStatus +/* static */ js::ResumeMode js::Debugger::onExceptionUnwind(JSContext* cx, AbstractFramePtr frame) { if (!cx->compartment()->isDebuggee()) - return JSTRAP_CONTINUE; + return ResumeMode::Continue; return slowPathOnExceptionUnwind(cx, frame); } /* static */ void js::Debugger::onNewWasmInstance(JSContext* cx, Handle<WasmInstanceObject*> wasmInstance) { if (cx->compartment()->isDebuggee()) slowPathOnNewWasmInstance(cx, wasmInstance);
--- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -876,50 +876,50 @@ Debugger::hasAnyLiveHooks(JSRuntime* rt) if (!frameObj->getReservedSlot(JSSLOT_DEBUGFRAME_ONSTEP_HANDLER).isUndefined() || !frameObj->getReservedSlot(JSSLOT_DEBUGFRAME_ONPOP_HANDLER).isUndefined()) return true; } return false; } -/* static */ JSTrapStatus +/* static */ ResumeMode Debugger::slowPathOnEnterFrame(JSContext* cx, AbstractFramePtr frame) { RootedValue rval(cx); - JSTrapStatus status = dispatchHook( + ResumeMode resumeMode = dispatchHook( cx, [frame](Debugger* dbg) -> bool { return dbg->observesFrame(frame) && dbg->observesEnterFrame(); }, - [&](Debugger* dbg) -> JSTrapStatus { + [&](Debugger* dbg) -> ResumeMode { return dbg->fireEnterFrame(cx, &rval); }); - switch (status) { - case JSTRAP_CONTINUE: + switch (resumeMode) { + case ResumeMode::Continue: break; - case JSTRAP_THROW: + case ResumeMode::Throw: cx->setPendingException(rval); break; - case JSTRAP_ERROR: + case ResumeMode::Terminate: cx->clearPendingException(); break; - case JSTRAP_RETURN: + case ResumeMode::Return: frame.setReturnValue(rval); break; default: - MOZ_CRASH("bad Debugger::onEnterFrame JSTrapStatus value"); - } - - return status; + MOZ_CRASH("bad Debugger::onEnterFrame resume mode"); + } + + return resumeMode; } static void DebuggerFrame_maybeDecrementFrameScriptStepModeCount(FreeOp* fop, AbstractFramePtr frame, NativeObject* frameobj); static void DebuggerFrame_freeScriptFrameIterData(FreeOp* fop, JSObject* obj); @@ -944,19 +944,19 @@ Debugger::slowPathOnLeaveFrame(JSContext // called, the frame will not be present in the Debugger frame maps. Rooted<DebuggerFrameVector> frames(cx, DebuggerFrameVector(cx)); if (!getDebuggerFrames(frame, &frames)) return false; if (frames.empty()) return frameOk; /* Save the frame's completion value. */ - JSTrapStatus status; + ResumeMode resumeMode; RootedValue value(cx); - Debugger::resultToCompletion(cx, frameOk, frame.returnValue(), &status, &value); + Debugger::resultToCompletion(cx, frameOk, frame.returnValue(), &resumeMode, &value); // This path can be hit via unwinding the stack due to over-recursion or // OOM. In those cases, don't fire the frames' onPop handlers, because // invoking JS will only trigger the same condition. See // slowPathOnExceptionUnwind. if (!cx->isThrowingOverRecursed() && !cx->isThrowingOutOfMemory()) { /* For each Debugger.Frame, fire its onPop handler, if any. */ for (size_t i = 0; i < frames.length(); i++) { @@ -970,135 +970,135 @@ Debugger::slowPathOnLeaveFrame(JSContext Maybe<AutoCompartment> ac; ac.emplace(cx, dbg->object); RootedValue wrappedValue(cx, value); RootedValue completion(cx); if (!dbg->wrapDebuggeeValue(cx, &wrappedValue)) { - status = dbg->reportUncaughtException(ac); + resumeMode = dbg->reportUncaughtException(ac); break; } /* Call the onPop handler. */ - JSTrapStatus nextStatus = status; + ResumeMode nextResumeMode = resumeMode; RootedValue nextValue(cx, wrappedValue); - bool success = handler->onPop(cx, frameobj, nextStatus, &nextValue); - nextStatus = dbg->processParsedHandlerResult(ac, frame, pc, success, nextStatus, - &nextValue); + bool success = handler->onPop(cx, frameobj, nextResumeMode, &nextValue); + nextResumeMode = dbg->processParsedHandlerResult(ac, frame, pc, success, + nextResumeMode, &nextValue); /* * At this point, we are back in the debuggee compartment, and any error has * been wrapped up as a completion value. */ MOZ_ASSERT(cx->compartment() == debuggeeGlobal->compartment()); MOZ_ASSERT(!cx->isExceptionPending()); - /* JSTRAP_CONTINUE means "make no change". */ - if (nextStatus != JSTRAP_CONTINUE) { - status = nextStatus; + /* ResumeMode::Continue means "make no change". */ + if (nextResumeMode != ResumeMode::Continue) { + resumeMode = nextResumeMode; value = nextValue; } } } } - /* Establish (status, value) as our resumption value. */ - switch (status) { - case JSTRAP_RETURN: + /* Establish (resumeMode, value) as our resumption value. */ + switch (resumeMode) { + case ResumeMode::Return: frame.setReturnValue(value); return true; - case JSTRAP_THROW: + case ResumeMode::Throw: cx->setPendingException(value); return false; - case JSTRAP_ERROR: + case ResumeMode::Terminate: MOZ_ASSERT(!cx->isExceptionPending()); return false; default: - MOZ_CRASH("bad final trap status"); - } -} - -/* static */ JSTrapStatus + MOZ_CRASH("bad final onLeaveFrame resume mode"); + } +} + +/* static */ ResumeMode Debugger::slowPathOnDebuggerStatement(JSContext* cx, AbstractFramePtr frame) { RootedValue rval(cx); - JSTrapStatus status = dispatchHook( + ResumeMode resumeMode = dispatchHook( cx, [](Debugger* dbg) -> bool { return dbg->getHook(OnDebuggerStatement); }, - [&](Debugger* dbg) -> JSTrapStatus { + [&](Debugger* dbg) -> ResumeMode { return dbg->fireDebuggerStatement(cx, &rval); }); - switch (status) { - case JSTRAP_CONTINUE: - case JSTRAP_ERROR: + switch (resumeMode) { + case ResumeMode::Continue: + case ResumeMode::Terminate: break; - case JSTRAP_RETURN: + case ResumeMode::Return: frame.setReturnValue(rval); break; - case JSTRAP_THROW: + case ResumeMode::Throw: cx->setPendingException(rval); break; default: - MOZ_CRASH("Invalid onDebuggerStatement trap status"); - } - - return status; -} - -/* static */ JSTrapStatus + MOZ_CRASH("Invalid onDebuggerStatement resume mode"); + } + + return resumeMode; +} + +/* static */ ResumeMode Debugger::slowPathOnExceptionUnwind(JSContext* cx, AbstractFramePtr frame) { // Invoking more JS on an over-recursed stack or after OOM is only going // to result in more of the same error. if (cx->isThrowingOverRecursed() || cx->isThrowingOutOfMemory()) - return JSTRAP_CONTINUE; + return ResumeMode::Continue; // The Debugger API mustn't muck with frames from self-hosted scripts. if (frame.hasScript() && frame.script()->selfHosted()) - return JSTRAP_CONTINUE; + return ResumeMode::Continue; RootedValue rval(cx); - JSTrapStatus status = dispatchHook( + ResumeMode resumeMode = dispatchHook( cx, [](Debugger* dbg) -> bool { return dbg->getHook(OnExceptionUnwind); }, - [&](Debugger* dbg) -> JSTrapStatus { + [&](Debugger* dbg) -> ResumeMode { return dbg->fireExceptionUnwind(cx, &rval); }); - switch (status) { - case JSTRAP_CONTINUE: + switch (resumeMode) { + case ResumeMode::Continue: break; - case JSTRAP_THROW: + case ResumeMode::Throw: cx->setPendingException(rval); break; - case JSTRAP_ERROR: + case ResumeMode::Terminate: cx->clearPendingException(); break; - case JSTRAP_RETURN: + case ResumeMode::Return: cx->clearPendingException(); frame.setReturnValue(rval); break; default: - MOZ_CRASH("Invalid onExceptionUnwind trap status"); - } - - return status; + MOZ_CRASH("Invalid onExceptionUnwind resume mode"); + } + + return resumeMode; } // TODO: Remove Remove this function when all properties/methods returning a /// DebuggerEnvironment have been given a C++ interface (bug 1271649). bool Debugger::wrapEnvironment(JSContext* cx, Handle<Env*> env, MutableHandleValue rval) { if (!env) { @@ -1354,17 +1354,17 @@ Debugger::unwrapPropertyDescriptor(JSCon return false; } desc.setSetterObject(set); } return true; } -JSTrapStatus +ResumeMode Debugger::reportUncaughtException(Maybe<AutoCompartment>& ac) { JSContext* cx = ac->context(); // Uncaught exceptions arise from Debugger code, and so we must already be // in an NX section. MOZ_ASSERT(EnterDebuggeeNoExecute::isLockedInStack(cx, *this)); @@ -1391,122 +1391,122 @@ Debugger::reportUncaughtException(Maybe< * And if not, or if PrepareScriptEnvironmentAndInvoke somehow left * an exception on cx (which it totally shouldn't do), just give * up. */ cx->clearPendingException(); } ac.reset(); - return JSTRAP_ERROR; -} - -JSTrapStatus + return ResumeMode::Terminate; +} + +ResumeMode Debugger::handleUncaughtExceptionHelper(Maybe<AutoCompartment>& ac, MutableHandleValue* vp, const Maybe<HandleValue>& thisVForCheck, AbstractFramePtr frame) { JSContext* cx = ac->context(); // Uncaught exceptions arise from Debugger code, and so we must already be // in an NX section. MOZ_ASSERT(EnterDebuggeeNoExecute::isLockedInStack(cx, *this)); if (cx->isExceptionPending()) { if (uncaughtExceptionHook) { RootedValue exc(cx); if (!cx->getPendingException(&exc)) - return JSTRAP_ERROR; + return ResumeMode::Terminate; cx->clearPendingException(); RootedValue fval(cx, ObjectValue(*uncaughtExceptionHook)); RootedValue rv(cx); if (js::Call(cx, fval, object, exc, &rv)) { if (vp) { - JSTrapStatus status = JSTRAP_CONTINUE; - if (processResumptionValue(ac, frame, thisVForCheck, rv, status, *vp)) - return status; + ResumeMode resumeMode = ResumeMode::Continue; + if (processResumptionValue(ac, frame, thisVForCheck, rv, resumeMode, *vp)) + return resumeMode; } else { - return JSTRAP_CONTINUE; + return ResumeMode::Continue; } } } return reportUncaughtException(ac); } ac.reset(); - return JSTRAP_ERROR; -} - -JSTrapStatus + return ResumeMode::Terminate; +} + +ResumeMode Debugger::handleUncaughtException(Maybe<AutoCompartment>& ac, MutableHandleValue vp, const Maybe<HandleValue>& thisVForCheck, AbstractFramePtr frame) { return handleUncaughtExceptionHelper(ac, &vp, thisVForCheck, frame); } -JSTrapStatus +ResumeMode Debugger::handleUncaughtException(Maybe<AutoCompartment>& ac) { return handleUncaughtExceptionHelper(ac, nullptr, mozilla::Nothing(), NullFramePtr()); } /* static */ void Debugger::resultToCompletion(JSContext* cx, bool ok, const Value& rv, - JSTrapStatus* status, MutableHandleValue value) + ResumeMode* resumeMode, MutableHandleValue value) { MOZ_ASSERT_IF(ok, !cx->isExceptionPending()); if (ok) { - *status = JSTRAP_RETURN; + *resumeMode = ResumeMode::Return; value.set(rv); } else if (cx->isExceptionPending()) { - *status = JSTRAP_THROW; + *resumeMode = ResumeMode::Throw; if (!cx->getPendingException(value)) - *status = JSTRAP_ERROR; + *resumeMode = ResumeMode::Terminate; cx->clearPendingException(); } else { - *status = JSTRAP_ERROR; + *resumeMode = ResumeMode::Terminate; value.setUndefined(); } } bool -Debugger::newCompletionValue(JSContext* cx, JSTrapStatus status, const Value& value_, +Debugger::newCompletionValue(JSContext* cx, ResumeMode resumeMode, const Value& value_, MutableHandleValue result) { /* * We must be in the debugger's compartment, since that's where we want * to construct the completion value. */ assertSameCompartment(cx, object.get()); assertSameCompartment(cx, value_); RootedId key(cx); RootedValue value(cx, value_); - switch (status) { - case JSTRAP_RETURN: + switch (resumeMode) { + case ResumeMode::Return: key = NameToId(cx->names().return_); break; - case JSTRAP_THROW: + case ResumeMode::Throw: key = NameToId(cx->names().throw_); break; - case JSTRAP_ERROR: + case ResumeMode::Terminate: result.setNull(); return true; default: - MOZ_CRASH("bad status passed to Debugger::newCompletionValue"); - } - - /* Common tail for JSTRAP_RETURN and JSTRAP_THROW. */ + MOZ_CRASH("bad resume mode passed to Debugger::newCompletionValue"); + } + + // Common tail for ResumeMode::Return and ResumeMode::Throw. RootedPlainObject obj(cx, NewBuiltinClassInstance<PlainObject>(cx)); if (!obj || !NativeDefineDataProperty(cx, obj, key, value, JSPROP_ENUMERATE)) { return false; } result.setObject(*obj); @@ -1515,96 +1515,96 @@ Debugger::newCompletionValue(JSContext* bool Debugger::receiveCompletionValue(Maybe<AutoCompartment>& ac, bool ok, HandleValue val, MutableHandleValue vp) { JSContext* cx = ac->context(); - JSTrapStatus status; + ResumeMode resumeMode; RootedValue value(cx); - resultToCompletion(cx, ok, val, &status, &value); + resultToCompletion(cx, ok, val, &resumeMode, &value); ac.reset(); return wrapDebuggeeValue(cx, &value) && - newCompletionValue(cx, status, value, vp); + newCompletionValue(cx, resumeMode, value, vp); } static bool -GetStatusProperty(JSContext* cx, HandleObject obj, HandlePropertyName name, JSTrapStatus status, - JSTrapStatus& statusp, MutableHandleValue vp, int* hits) +GetResumptionProperty(JSContext* cx, HandleObject obj, HandlePropertyName name, ResumeMode namedMode, + ResumeMode& resumeMode, MutableHandleValue vp, int* hits) { bool found; if (!HasProperty(cx, obj, name, &found)) return false; if (found) { ++*hits; - statusp = status; + resumeMode = namedMode; if (!GetProperty(cx, obj, obj, name, vp)) return false; } return true; } static bool -ParseResumptionValueAsObject(JSContext* cx, HandleValue rv, JSTrapStatus& statusp, +ParseResumptionValueAsObject(JSContext* cx, HandleValue rv, ResumeMode& resumeMode, MutableHandleValue vp) { int hits = 0; if (rv.isObject()) { RootedObject obj(cx, &rv.toObject()); - if (!GetStatusProperty(cx, obj, cx->names().return_, JSTRAP_RETURN, statusp, vp, &hits)) - return false; - if (!GetStatusProperty(cx, obj, cx->names().throw_, JSTRAP_THROW, statusp, vp, &hits)) + if (!GetResumptionProperty(cx, obj, cx->names().return_, ResumeMode::Return, resumeMode, vp, &hits)) + return false; + if (!GetResumptionProperty(cx, obj, cx->names().throw_, ResumeMode::Throw, resumeMode, vp, &hits)) return false; } if (hits != 1) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_BAD_RESUMPTION); return false; } return true; } static bool -ParseResumptionValue(JSContext* cx, HandleValue rval, JSTrapStatus& statusp, MutableHandleValue vp) +ParseResumptionValue(JSContext* cx, HandleValue rval, ResumeMode& resumeMode, MutableHandleValue vp) { if (rval.isUndefined()) { - statusp = JSTRAP_CONTINUE; + resumeMode = ResumeMode::Continue; vp.setUndefined(); return true; } if (rval.isNull()) { - statusp = JSTRAP_ERROR; + resumeMode = ResumeMode::Terminate; vp.setUndefined(); return true; } - return ParseResumptionValueAsObject(cx, rval, statusp, vp); + return ParseResumptionValueAsObject(cx, rval, resumeMode, vp); } static bool CheckResumptionValue(JSContext* cx, AbstractFramePtr frame, const Maybe<HandleValue>& maybeThisv, - JSTrapStatus status, MutableHandleValue vp) -{ - if (status == JSTRAP_RETURN && frame && frame.isFunctionFrame()) { + ResumeMode resumeMode, MutableHandleValue vp) +{ + if (resumeMode == ResumeMode::Return && frame && frame.isFunctionFrame()) { // Don't let a { return: ... } resumption value make a generator // function violate the iterator protocol. The return value from // such a frame must have the form { done: <bool>, value: <anything> }. RootedFunction callee(cx, frame.callee()); if (callee->isGenerator()) { if (!CheckGeneratorResumptionValue(cx, vp)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_BAD_YIELD); return false; } } } if (maybeThisv.isSome()) { const HandleValue& thisv = maybeThisv.ref(); - if (status == JSTRAP_RETURN && vp.isPrimitive()) { + if (resumeMode == ResumeMode::Return && vp.isPrimitive()) { if (vp.isUndefined()) { if (thisv.isMagic(JS_UNINITIALIZED_LEXICAL)) return ThrowUninitializedThis(cx, frame); vp.set(thisv); } else { ReportValueError(cx, JSMSG_BAD_DERIVED_RETURN, JSDVG_IGNORE_STACK, vp, nullptr); return false; @@ -1633,99 +1633,99 @@ GetThisValueForCheck(JSContext* cx, Abst } return true; } bool Debugger::processResumptionValue(Maybe<AutoCompartment>& ac, AbstractFramePtr frame, const Maybe<HandleValue>& maybeThisv, HandleValue rval, - JSTrapStatus& statusp, MutableHandleValue vp) + ResumeMode& resumeMode, MutableHandleValue vp) { JSContext* cx = ac->context(); - if (!ParseResumptionValue(cx, rval, statusp, vp) || + if (!ParseResumptionValue(cx, rval, resumeMode, vp) || !unwrapDebuggeeValue(cx, vp) || - !CheckResumptionValue(cx, frame, maybeThisv, statusp, vp)) + !CheckResumptionValue(cx, frame, maybeThisv, resumeMode, vp)) { return false; } ac.reset(); if (!cx->compartment()->wrap(cx, vp)) { - statusp = JSTRAP_ERROR; + resumeMode = ResumeMode::Terminate; vp.setUndefined(); } return true; } -JSTrapStatus +ResumeMode Debugger::processParsedHandlerResultHelper(Maybe<AutoCompartment>& ac, AbstractFramePtr frame, const Maybe<HandleValue>& maybeThisv, bool success, - JSTrapStatus status, MutableHandleValue vp) + ResumeMode resumeMode, MutableHandleValue vp) { if (!success) return handleUncaughtException(ac, vp, maybeThisv, frame); JSContext* cx = ac->context(); if (!unwrapDebuggeeValue(cx, vp) || - !CheckResumptionValue(cx, frame, maybeThisv, status, vp)) + !CheckResumptionValue(cx, frame, maybeThisv, resumeMode, vp)) { return handleUncaughtException(ac, vp, maybeThisv, frame); } ac.reset(); if (!cx->compartment()->wrap(cx, vp)) { - status = JSTRAP_ERROR; + resumeMode = ResumeMode::Terminate; vp.setUndefined(); } - return status; -} - -JSTrapStatus + return resumeMode; +} + +ResumeMode Debugger::processParsedHandlerResult(Maybe<AutoCompartment>& ac, AbstractFramePtr frame, - jsbytecode* pc, bool success, JSTrapStatus status, + jsbytecode* pc, bool success, ResumeMode resumeMode, MutableHandleValue vp) { JSContext* cx = ac->context(); RootedValue thisv(cx); Maybe<HandleValue> maybeThisv; if (!GetThisValueForCheck(cx, frame, pc, &thisv, maybeThisv)) { ac.reset(); - return JSTRAP_ERROR; - } - - return processParsedHandlerResultHelper(ac, frame, maybeThisv, success, status, vp); -} - -JSTrapStatus + return ResumeMode::Terminate; + } + + return processParsedHandlerResultHelper(ac, frame, maybeThisv, success, resumeMode, vp); +} + +ResumeMode Debugger::processHandlerResult(Maybe<AutoCompartment>& ac, bool success, const Value& rv, AbstractFramePtr frame, jsbytecode* pc, MutableHandleValue vp) { JSContext* cx = ac->context(); RootedValue thisv(cx); Maybe<HandleValue> maybeThisv; if (!GetThisValueForCheck(cx, frame, pc, &thisv, maybeThisv)) { ac.reset(); - return JSTRAP_ERROR; + return ResumeMode::Terminate; } if (!success) return handleUncaughtException(ac, vp, maybeThisv, frame); RootedValue rootRv(cx, rv); - JSTrapStatus status = JSTRAP_CONTINUE; - success = ParseResumptionValue(cx, rootRv, status, vp); - - return processParsedHandlerResultHelper(ac, frame, maybeThisv, success, status, vp); + ResumeMode resumeMode = ResumeMode::Continue; + success = ParseResumptionValue(cx, rootRv, resumeMode, vp); + + return processParsedHandlerResultHelper(ac, frame, maybeThisv, success, resumeMode, vp); } static bool CallMethodIfPresent(JSContext* cx, HandleObject obj, const char* name, size_t argc, Value* argv, MutableHandleValue rval) { rval.setUndefined(); JSAtom* atom = Atomize(cx, name, strlen(name)); @@ -1746,17 +1746,17 @@ CallMethodIfPresent(JSContext* cx, Handl for (size_t i = 0; i < argc; i++) args[i].set(argv[i]); rval.setObject(*obj); // overwritten by successful Call return js::Call(cx, fval, rval, args, rval); } -JSTrapStatus +ResumeMode Debugger::fireDebuggerStatement(JSContext* cx, MutableHandleValue vp) { RootedObject hook(cx, getHook(OnDebuggerStatement)); MOZ_ASSERT(hook); MOZ_ASSERT(hook->isCallable()); Maybe<AutoCompartment> ac; ac.emplace(cx, object); @@ -1767,48 +1767,48 @@ Debugger::fireDebuggerStatement(JSContex return reportUncaughtException(ac); RootedValue fval(cx, ObjectValue(*hook)); RootedValue rv(cx); bool ok = js::Call(cx, fval, object, scriptFrame, &rv); return processHandlerResult(ac, ok, rv, iter.abstractFramePtr(), iter.pc(), vp); } -JSTrapStatus +ResumeMode Debugger::fireExceptionUnwind(JSContext* cx, MutableHandleValue vp) { RootedObject hook(cx, getHook(OnExceptionUnwind)); MOZ_ASSERT(hook); MOZ_ASSERT(hook->isCallable()); RootedValue exc(cx); if (!cx->getPendingException(&exc)) - return JSTRAP_ERROR; + return ResumeMode::Terminate; cx->clearPendingException(); Maybe<AutoCompartment> ac; ac.emplace(cx, object); RootedValue scriptFrame(cx); RootedValue wrappedExc(cx, exc); FrameIter iter(cx); if (!getScriptFrame(cx, iter, &scriptFrame) || !wrapDebuggeeValue(cx, &wrappedExc)) return reportUncaughtException(ac); RootedValue fval(cx, ObjectValue(*hook)); RootedValue rv(cx); bool ok = js::Call(cx, fval, object, scriptFrame, wrappedExc, &rv); - JSTrapStatus st = processHandlerResult(ac, ok, rv, iter.abstractFramePtr(), iter.pc(), vp); - if (st == JSTRAP_CONTINUE) + ResumeMode resumeMode = processHandlerResult(ac, ok, rv, iter.abstractFramePtr(), iter.pc(), vp); + if (resumeMode == ResumeMode::Continue) cx->setPendingException(exc); - return st; -} - -JSTrapStatus + return resumeMode; +} + +ResumeMode Debugger::fireEnterFrame(JSContext* cx, MutableHandleValue vp) { RootedObject hook(cx, getHook(OnEnterFrame)); MOZ_ASSERT(hook); MOZ_ASSERT(hook->isCallable()); Maybe<AutoCompartment> ac; ac.emplace(cx, object); @@ -1872,18 +1872,18 @@ Debugger::fireOnGarbageCollectionHook(JS RootedValue fval(cx, ObjectValue(*hook)); RootedValue dataVal(cx, ObjectValue(*dataObj)); RootedValue rv(cx); if (!js::Call(cx, fval, object, dataVal, &rv)) handleUncaughtException(ac); } template <typename HookIsEnabledFun /* bool (Debugger*) */, - typename FireHookFun /* JSTrapStatus (Debugger*) */> -/* static */ JSTrapStatus + typename FireHookFun /* ResumeMode (Debugger*) */> +/* static */ ResumeMode Debugger::dispatchHook(JSContext* cx, HookIsEnabledFun hookIsEnabled, FireHookFun fireHook) { /* * Determine which debuggers will receive this event, and in what order. * Make a copy of the list, since the original is mutable and we will be * calling into arbitrary JS. * * Note: In the general case, 'triggered' contains references to objects in @@ -1891,86 +1891,86 @@ Debugger::dispatchHook(JSContext* cx, Ho */ AutoValueVector triggered(cx); Handle<GlobalObject*> global = cx->global(); if (GlobalObject::DebuggerVector* debuggers = global->getDebuggers()) { for (auto p = debuggers->begin(); p != debuggers->end(); p++) { Debugger* dbg = *p; if (dbg->enabled && hookIsEnabled(dbg)) { if (!triggered.append(ObjectValue(*dbg->toJSObject()))) - return JSTRAP_ERROR; + return ResumeMode::Terminate; } } } /* * Deliver the event to each debugger, checking again to make sure it * should still be delivered. */ for (Value* p = triggered.begin(); p != triggered.end(); p++) { Debugger* dbg = Debugger::fromJSObject(&p->toObject()); EnterDebuggeeNoExecute nx(cx, *dbg); if (dbg->debuggees.has(global) && dbg->enabled && hookIsEnabled(dbg)) { - JSTrapStatus st = fireHook(dbg); - if (st != JSTRAP_CONTINUE) - return st; - } - } - return JSTRAP_CONTINUE; + ResumeMode resumeMode = fireHook(dbg); + if (resumeMode != ResumeMode::Continue) + return resumeMode; + } + } + return ResumeMode::Continue; } void Debugger::slowPathOnNewScript(JSContext* cx, HandleScript script) { - JSTrapStatus status = dispatchHook( + ResumeMode resumeMode = dispatchHook( cx, [script](Debugger* dbg) -> bool { return dbg->observesNewScript() && dbg->observesScript(script); }, - [&](Debugger* dbg) -> JSTrapStatus { + [&](Debugger* dbg) -> ResumeMode { Rooted<DebuggerScriptReferent> scriptReferent(cx, script.get()); dbg->fireNewScript(cx, scriptReferent); - return JSTRAP_CONTINUE; + return ResumeMode::Continue; }); // dispatchHook may fail due to OOM. This OOM is not handlable at the // callsites of onNewScript in the engine. - if (status == JSTRAP_ERROR) { + if (resumeMode == ResumeMode::Terminate) { cx->clearPendingException(); return; } - MOZ_ASSERT(status == JSTRAP_CONTINUE); + MOZ_ASSERT(resumeMode == ResumeMode::Continue); } void Debugger::slowPathOnNewWasmInstance(JSContext* cx, Handle<WasmInstanceObject*> wasmInstance) { - JSTrapStatus status = dispatchHook( + ResumeMode resumeMode = dispatchHook( cx, [wasmInstance](Debugger* dbg) -> bool { return dbg->observesNewScript() && dbg->observesGlobal(&wasmInstance->global()); }, - [&](Debugger* dbg) -> JSTrapStatus { + [&](Debugger* dbg) -> ResumeMode { Rooted<DebuggerScriptReferent> scriptReferent(cx, wasmInstance.get()); dbg->fireNewScript(cx, scriptReferent); - return JSTRAP_CONTINUE; + return ResumeMode::Continue; }); // dispatchHook may fail due to OOM. This OOM is not handlable at the // callsites of onNewWasmInstance in the engine. - if (status == JSTRAP_ERROR) { + if (resumeMode == ResumeMode::Terminate) { cx->clearPendingException(); return; } - MOZ_ASSERT(status == JSTRAP_CONTINUE); -} - -/* static */ JSTrapStatus + MOZ_ASSERT(resumeMode == ResumeMode::Continue); +} + +/* static */ ResumeMode Debugger::onTrap(JSContext* cx, MutableHandleValue vp) { FrameIter iter(cx); JS::AutoSaveExceptionState saveExc(cx); Rooted<GlobalObject*> global(cx); BreakpointSite* site; bool isJS; // true when iter.hasScript(), false when iter.isWasm() jsbytecode* pc; // valid when isJS == true @@ -1995,17 +1995,17 @@ Debugger::onTrap(JSContext* cx, MutableH /* Build list of breakpoint handlers. */ Vector<Breakpoint*> triggered(cx); for (Breakpoint* bp = site->firstBreakpoint(); bp; bp = bp->nextInSite()) { // Skip a breakpoint that is not set for the current wasm::Instance -- // single wasm::Code can handle breakpoints for mutiple instances. if (!isJS && &bp->asWasm()->wasmInstance->instance() != iter.wasmInstance()) continue; if (!triggered.append(bp)) - return JSTRAP_ERROR; + return ResumeMode::Terminate; } for (Breakpoint** p = triggered.begin(); p != triggered.end(); p++) { Breakpoint* bp = *p; /* Handlers can clear breakpoints. Check that bp still exists. */ if (!site || !site->hasBreakpoint(bp)) continue; @@ -2029,39 +2029,39 @@ Debugger::onTrap(JSContext* cx, MutableH EnterDebuggeeNoExecute nx(cx, *dbg); RootedValue scriptFrame(cx); if (!dbg->getScriptFrame(cx, iter, &scriptFrame)) return dbg->reportUncaughtException(ac); RootedValue rv(cx); Rooted<JSObject*> handler(cx, bp->handler); bool ok = CallMethodIfPresent(cx, handler, "hit", 1, scriptFrame.address(), &rv); - JSTrapStatus st = dbg->processHandlerResult(ac, ok, rv, iter.abstractFramePtr(), - iter.pc(), vp); - if (st != JSTRAP_CONTINUE) - return st; + ResumeMode resumeMode = dbg->processHandlerResult(ac, ok, rv, iter.abstractFramePtr(), + iter.pc(), vp); + if (resumeMode != ResumeMode::Continue) + return resumeMode; /* Calling JS code invalidates site. Reload it. */ if (isJS) site = iter.script()->getBreakpointSite(pc); else site = iter.wasmInstance()->debug().getOrCreateBreakpointSite(cx, bytecodeOffset); } } // By convention, return the true op to the interpreter in vp, and return // undefined in vp to the wasm debug trap. if (isJS) vp.setInt32(JSOp(*pc)); else vp.set(UndefinedValue()); - return JSTRAP_CONTINUE; -} - -/* static */ JSTrapStatus + return ResumeMode::Continue; +} + +/* static */ ResumeMode Debugger::onSingleStep(JSContext* cx, MutableHandleValue vp) { FrameIter iter(cx); /* * We may be stepping over a JSOP_EXCEPTION, that pushes the context's * pending exception for a 'catch' clause to handle. Don't let the * onStep handlers mess with that (other than by returning a resumption @@ -2070,17 +2070,17 @@ Debugger::onSingleStep(JSContext* cx, Mu JS::AutoSaveExceptionState saveExc(cx); /* * Build list of Debugger.Frame instances referring to this frame with * onStep handlers. */ Rooted<DebuggerFrameVector> frames(cx, DebuggerFrameVector(cx)); if (!getDebuggerFrames(iter.abstractFramePtr(), &frames)) - return JSTRAP_ERROR; + return ResumeMode::Terminate; #ifdef DEBUG /* * Validate the single-step count on this frame's script, to ensure that * we're not receiving traps we didn't ask for. Even when frames is * non-empty (and thus we know this trap was requested), do the check * anyway, to make sure the count has the correct non-zero value. * @@ -2119,29 +2119,29 @@ Debugger::onSingleStep(JSContext* cx, Mu continue; Debugger* dbg = Debugger::fromChildJSObject(frame); EnterDebuggeeNoExecute nx(cx, *dbg); Maybe<AutoCompartment> ac; ac.emplace(cx, dbg->object); - JSTrapStatus status = JSTRAP_CONTINUE; - bool success = handler->onStep(cx, frame, status, vp); - status = dbg->processParsedHandlerResult(ac, iter.abstractFramePtr(), iter.pc(), success, - status, vp); - if (status != JSTRAP_CONTINUE) - return status; + ResumeMode resumeMode = ResumeMode::Continue; + bool success = handler->onStep(cx, frame, resumeMode, vp); + resumeMode = dbg->processParsedHandlerResult(ac, iter.abstractFramePtr(), iter.pc(), success, + resumeMode, vp); + if (resumeMode != ResumeMode::Continue) + return resumeMode; } vp.setUndefined(); - return JSTRAP_CONTINUE; -} - -JSTrapStatus + return ResumeMode::Continue; +} + +ResumeMode Debugger::fireNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global, MutableHandleValue vp) { RootedObject hook(cx, getHook(OnNewGlobalObject)); MOZ_ASSERT(hook); MOZ_ASSERT(hook->isCallable()); Maybe<AutoCompartment> ac; ac.emplace(cx, object); @@ -2163,20 +2163,20 @@ Debugger::fireNewGlobalObject(JSContext* JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_RESUMPTION_VALUE_DISALLOWED); ok = false; } // NB: Even though we don't care about what goes into it, we have to pass vp // to handleUncaughtException so that it parses resumption values from the // uncaughtExceptionHook and tells the caller whether we should execute the // rest of the onNewGlobalObject hooks or not. - JSTrapStatus status = ok ? JSTRAP_CONTINUE - : handleUncaughtException(ac, vp); + ResumeMode resumeMode = ok ? ResumeMode::Continue + : handleUncaughtException(ac, vp); MOZ_ASSERT(!cx->isExceptionPending()); - return status; + return resumeMode; } void Debugger::slowPathOnNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global) { MOZ_ASSERT(!cx->runtime()->onNewGlobalObjectWatchers().isEmpty()); if (global->compartment()->creationOptions().invisibleToDebugger()) return; @@ -2193,34 +2193,34 @@ Debugger::slowPathOnNewGlobalObject(JSCo JS::ExposeObjectToActiveJS(obj); if (!watchers.append(obj)) { if (cx->isExceptionPending()) cx->clearPendingException(); return; } } - JSTrapStatus status = JSTRAP_CONTINUE; + ResumeMode resumeMode = ResumeMode::Continue; RootedValue value(cx); for (size_t i = 0; i < watchers.length(); i++) { Debugger* dbg = fromJSObject(watchers[i]); EnterDebuggeeNoExecute nx(cx, *dbg); // We disallow resumption values from onNewGlobalObject hooks, because we // want the debugger hooks for global object creation to be infallible. // But if an onNewGlobalObject hook throws, and the uncaughtExceptionHook // decides to raise an error, we want to at least avoid invoking the rest // of the onNewGlobalObject handlers in the list (not for any super // compelling reason, just because it seems like the right thing to do). // So we ignore whatever comes out in |value|, but break out of the loop - // if a non-success trap status is returned. + // if a non-success resume mode is returned. if (dbg->observesNewGlobalObject()) { - status = dbg->fireNewGlobalObject(cx, global, &value); - if (status != JSTRAP_CONTINUE && status != JSTRAP_RETURN) + resumeMode = dbg->fireNewGlobalObject(cx, global, &value); + if (resumeMode != ResumeMode::Continue && resumeMode != ResumeMode::Return) break; } } MOZ_ASSERT(!cx->isExceptionPending()); } /* static */ bool Debugger::slowPathOnLogAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame frame, @@ -2298,17 +2298,17 @@ Debugger::appendAllocationSite(JSContext allocationsLog.popFront(); MOZ_ASSERT(allocationsLog.length() == maxAllocationsLogLength); allocationsLogOverflowed = true; } return true; } -JSTrapStatus +ResumeMode Debugger::firePromiseHook(JSContext* cx, Hook hook, HandleObject promise, MutableHandleValue vp) { MOZ_ASSERT(hook == OnNewPromise || hook == OnPromiseSettled); RootedObject hookObj(cx, getHook(hook)); MOZ_ASSERT(hookObj); MOZ_ASSERT(hookObj->isCallable()); @@ -2325,52 +2325,52 @@ Debugger::firePromiseHook(JSContext* cx, RootedValue rv(cx); bool ok = js::Call(cx, fval, object, dbgObj, &rv); if (ok && !rv.isUndefined()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_RESUMPTION_VALUE_DISALLOWED); ok = false; } - JSTrapStatus status = ok ? JSTRAP_CONTINUE - : handleUncaughtException(ac, vp); + ResumeMode resumeMode = ok ? ResumeMode::Continue + : handleUncaughtException(ac, vp); MOZ_ASSERT(!cx->isExceptionPending()); - return status; + return resumeMode; } /* static */ void Debugger::slowPathPromiseHook(JSContext* cx, Hook hook, Handle<PromiseObject*> promise) { MOZ_ASSERT(hook == OnNewPromise || hook == OnPromiseSettled); Maybe<AutoCompartment> ac; if (hook == OnNewPromise) ac.emplace(cx, promise); assertSameCompartment(cx, promise); RootedValue rval(cx); - JSTrapStatus status = dispatchHook( + ResumeMode resumeMode = dispatchHook( cx, [hook](Debugger* dbg) -> bool { return dbg->getHook(hook); }, - [&](Debugger* dbg) -> JSTrapStatus { + [&](Debugger* dbg) -> ResumeMode { (void) dbg->firePromiseHook(cx, hook, promise, &rval); - return JSTRAP_CONTINUE; + return ResumeMode::Continue; }); - if (status == JSTRAP_ERROR) { + if (resumeMode == ResumeMode::Terminate) { // The dispatch hook function might fail to append into the list of // Debuggers which are watching for the hook. cx->clearPendingException(); return; } // Promise hooks are infallible and we ignore errors from uncaught // exceptions by design. - MOZ_ASSERT(status == JSTRAP_CONTINUE); + MOZ_ASSERT(resumeMode == ResumeMode::Continue); } /*** Debugger code invalidation for observing execution ******************************************/ class MOZ_RAII ExecutionObservableCompartments : public Debugger::ExecutionObservableSet { HashSet<JSCompartment*> compartments_; @@ -7451,25 +7451,25 @@ ScriptedOnStepHandler::drop() void ScriptedOnStepHandler::trace(JSTracer* tracer) { TraceEdge(tracer, &object_, "OnStepHandlerFunction.object"); } bool -ScriptedOnStepHandler::onStep(JSContext* cx, HandleDebuggerFrame frame, JSTrapStatus& statusp, +ScriptedOnStepHandler::onStep(JSContext* cx, HandleDebuggerFrame frame, ResumeMode& resumeMode, MutableHandleValue vp) { RootedValue fval(cx, ObjectValue(*object_)); RootedValue rval(cx); if (!js::Call(cx, fval, frame, &rval)) return false; - return ParseResumptionValue(cx, rval, statusp, vp); + return ParseResumptionValue(cx, rval, resumeMode, vp); }; ScriptedOnPopHandler::ScriptedOnPopHandler(JSObject* object) : object_(object) { MOZ_ASSERT(object->isCallable()); } @@ -7488,31 +7488,31 @@ ScriptedOnPopHandler::drop() void ScriptedOnPopHandler::trace(JSTracer* tracer) { TraceEdge(tracer, &object_, "OnStepHandlerFunction.object"); } bool -ScriptedOnPopHandler::onPop(JSContext* cx, HandleDebuggerFrame frame, JSTrapStatus& statusp, +ScriptedOnPopHandler::onPop(JSContext* cx, HandleDebuggerFrame frame, ResumeMode& resumeMode, MutableHandleValue vp) { Debugger *dbg = frame->owner(); RootedValue completion(cx); - if (!dbg->newCompletionValue(cx, statusp, vp, &completion)) + if (!dbg->newCompletionValue(cx, resumeMode, vp, &completion)) return false; RootedValue fval(cx, ObjectValue(*object_)); RootedValue rval(cx); if (!js::Call(cx, fval, frame, completion, &rval)) return false; - return ParseResumptionValue(cx, rval, statusp, vp); + return ParseResumptionValue(cx, rval, resumeMode, vp); }; /* static */ NativeObject* DebuggerFrame::initClass(JSContext* cx, HandleObject dbgCtor, HandleObject obj) { Handle<GlobalObject*> global = obj.as<GlobalObject>(); RootedObject objProto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global)); @@ -7906,17 +7906,17 @@ EvaluateInEnv(JSContext* cx, Handle<Env* return false; return ExecuteKernel(cx, script, *env, NullValue(), frame, rval.address()); } static bool DebuggerGenericEval(JSContext* cx, const mozilla::Range<const char16_t> chars, HandleObject bindings, const EvalOptions& options, - JSTrapStatus& status, MutableHandleValue value, + ResumeMode& resumeMode, MutableHandleValue value, Debugger* dbg, HandleObject envArg, FrameIter* iter) { /* Either we're specifying the frame, or a global. */ MOZ_ASSERT_IF(iter, !envArg); MOZ_ASSERT_IF(!iter, envArg && IsGlobalLexicalEnvironment(envArg)); /* * Gather keys and values of bindings, if any. This must be done in the @@ -7987,41 +7987,41 @@ DebuggerGenericEval(JSContext* cx, const /* Run the code and produce the completion value. */ LeaveDebuggeeNoExecute nnx(cx); RootedValue rval(cx); AbstractFramePtr frame = iter ? iter->abstractFramePtr() : NullFramePtr(); bool ok = EvaluateInEnv(cx, env, frame, chars, options.filename() ? options.filename() : "debugger eval code", options.lineno(), &rval); - Debugger::resultToCompletion(cx, ok, rval, &status, value); + Debugger::resultToCompletion(cx, ok, rval, &resumeMode, value); ac.reset(); return dbg->wrapDebuggeeValue(cx, value); } /* static */ bool DebuggerFrame::eval(JSContext* cx, HandleDebuggerFrame frame, mozilla::Range<const char16_t> chars, - HandleObject bindings, const EvalOptions& options, JSTrapStatus& status, + HandleObject bindings, const EvalOptions& options, ResumeMode& resumeMode, MutableHandleValue value) { MOZ_ASSERT(frame->isLive()); Debugger* dbg = frame->owner(); Maybe<FrameIter> maybeIter; if (!DebuggerFrame::getFrameIter(cx, frame, maybeIter)) return false; FrameIter& iter = *maybeIter; UpdateFrameIterPc(iter); - return DebuggerGenericEval(cx, chars, bindings, options, status, value, dbg, nullptr, &iter); -} - -/* statuc */ bool + return DebuggerGenericEval(cx, chars, bindings, options, resumeMode, value, dbg, nullptr, &iter); +} + +/* static */ bool DebuggerFrame::isLive() const { return !!getPrivate(); } OnStepHandler* DebuggerFrame::onStepHandler() const { @@ -8663,22 +8663,22 @@ DebuggerFrame::evalMethod(JSContext* cx, if (!ValueToStableChars(cx, "Debugger.Frame.prototype.eval", args[0], stableChars)) return false; mozilla::Range<const char16_t> chars = stableChars.twoByteRange(); EvalOptions options; if (!ParseEvalOptions(cx, args.get(1), options)) return false; - JSTrapStatus status; + ResumeMode resumeMode; RootedValue value(cx); - if (!DebuggerFrame::eval(cx, frame, chars, nullptr, options, status, &value)) - return false; - - return frame->owner()->newCompletionValue(cx, status, value, args.rval()); + if (!DebuggerFrame::eval(cx, frame, chars, nullptr, options, resumeMode, &value)) + return false; + + return frame->owner()->newCompletionValue(cx, resumeMode, value, args.rval()); } /* static */ bool DebuggerFrame::evalWithBindingsMethod(JSContext* cx, unsigned argc, Value* vp) { THIS_DEBUGGER_FRAME(cx, argc, vp, "evalWithBindings", args, frame); if (!args.requireAtLeast(cx, "Debugger.Frame.prototype.evalWithBindings", 2)) return false; @@ -8694,22 +8694,22 @@ DebuggerFrame::evalWithBindingsMethod(JS RootedObject bindings(cx, NonNullObject(cx, args[1])); if (!bindings) return false; EvalOptions options; if (!ParseEvalOptions(cx, args.get(2), options)) return false; - JSTrapStatus status; + ResumeMode resumeMode; RootedValue value(cx); - if (!DebuggerFrame::eval(cx, frame, chars, bindings, options, status, &value)) - return false; - - return frame->owner()->newCompletionValue(cx, status, value, args.rval()); + if (!DebuggerFrame::eval(cx, frame, chars, bindings, options, resumeMode, &value)) + return false; + + return frame->owner()->newCompletionValue(cx, resumeMode, value, args.rval()); } /* static */ bool DebuggerFrame::construct(JSContext* cx, unsigned argc, Value* vp) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR, "Debugger.Frame"); return false; @@ -9731,22 +9731,22 @@ DebuggerObject::executeInGlobalMethod(JS return false; } mozilla::Range<const char16_t> chars = stableChars.twoByteRange(); EvalOptions options; if (!ParseEvalOptions(cx, args.get(1), options)) return false; - JSTrapStatus status; + ResumeMode resumeMode; RootedValue value(cx); - if (!DebuggerObject::executeInGlobal(cx, object, chars, nullptr, options, status, &value)) - return false; - - return object->owner()->newCompletionValue(cx, status, value, args.rval()); + if (!DebuggerObject::executeInGlobal(cx, object, chars, nullptr, options, resumeMode, &value)) + return false; + + return object->owner()->newCompletionValue(cx, resumeMode, value, args.rval()); } /* static */ bool DebuggerObject::executeInGlobalWithBindingsMethod(JSContext* cx, unsigned argc, Value* vp) { THIS_DEBUGOBJECT(cx, argc, vp, "executeInGlobalWithBindings", args, object); if (!args.requireAtLeast(cx, "Debugger.Object.prototype.executeInGlobalWithBindings", 2)) return false; @@ -9765,22 +9765,22 @@ DebuggerObject::executeInGlobalWithBindi RootedObject bindings(cx, NonNullObject(cx, args[1])); if (!bindings) return false; EvalOptions options; if (!ParseEvalOptions(cx, args.get(2), options)) return false; - JSTrapStatus status; + ResumeMode resumeMode; RootedValue value(cx); - if (!DebuggerObject::executeInGlobal(cx, object, chars, bindings, options, status, &value)) - return false; - - return object->owner()->newCompletionValue(cx, status, value, args.rval()); + if (!DebuggerObject::executeInGlobal(cx, object, chars, bindings, options, resumeMode, &value)) + return false; + + return object->owner()->newCompletionValue(cx, resumeMode, value, args.rval()); } /* static */ bool DebuggerObject::makeDebuggeeValueMethod(JSContext* cx, unsigned argc, Value* vp) { THIS_DEBUGOBJECT(cx, argc, vp, "makeDebuggeeValue", args, object); if (!args.requireAtLeast(cx, "Debugger.Object.prototype.makeDebuggeeValue", 1)) return false; @@ -10658,26 +10658,26 @@ DebuggerObject::forceLexicalInitializati } return true; } /* static */ bool DebuggerObject::executeInGlobal(JSContext* cx, HandleDebuggerObject object, mozilla::Range<const char16_t> chars, HandleObject bindings, - const EvalOptions& options, JSTrapStatus& status, + const EvalOptions& options, ResumeMode& resumeMode, MutableHandleValue value) { MOZ_ASSERT(object->isGlobal()); Rooted<GlobalObject*> referent(cx, &object->referent()->as<GlobalObject>()); Debugger* dbg = object->owner(); RootedObject globalLexical(cx, &referent->lexicalEnvironment()); - return DebuggerGenericEval(cx, chars, bindings, options, status, value, dbg, globalLexical, + return DebuggerGenericEval(cx, chars, bindings, options, resumeMode, value, dbg, globalLexical, nullptr); } /* static */ bool DebuggerObject::makeDebuggeeValue(JSContext* cx, HandleDebuggerObject object, HandleValue value_, MutableHandleValue result) { RootedObject referent(cx, object->referent());
--- a/js/src/vm/Debugger.h +++ b/js/src/vm/Debugger.h @@ -23,27 +23,65 @@ #include "js/HashTable.h" #include "js/Wrapper.h" #include "vm/GlobalObject.h" #include "vm/JSCompartment.h" #include "vm/JSContext.h" #include "vm/SavedStacks.h" #include "wasm/WasmJS.h" -enum JSTrapStatus { - JSTRAP_ERROR, - JSTRAP_CONTINUE, - JSTRAP_RETURN, - JSTRAP_THROW, - JSTRAP_LIMIT +namespace js { + +/** + * Tells how the JS engine should resume debuggee execution after firing a + * debugger hook. Most debugger hooks get to choose how the debuggee proceeds; + * see js/src/doc/Debugger/Conventions.md under "Resumption Values". + * + * Debugger::processHandlerResult() translates between JavaScript values and + * this enum. + * + * The values `ResumeMode::Throw` and `ResumeMode::Return` are always + * associated with a value (the exception value or return value). Sometimes + * this is represented as an explicit `JS::Value` variable or parameter, + * declared alongside the `ResumeMode`. In other cases, especially when + * ResumeMode is used as a return type (as in Debugger::onEnterFrame), the + * value is stashed in `cx`'s pending exception slot or the topmost frame's + * return value slot. + */ +enum class ResumeMode { + /** + * The debuggee should continue unchanged. + * + * This corresponds to a resumption value of `undefined`. + */ + Continue, + + /** + * Throw an exception in the debuggee. + * + * This corresponds to a resumption value of `{throw: <value>}`. + */ + Throw, + + /** + * Terminate the debuggee, as if it had been cancelled via the "slow + * script" ribbon. + * + * This corresponds to a resumption value of `null`. + */ + Terminate, + + /** + * Force the debuggee to return from the current frame. + * + * This corresponds to a resumption value of `{return: <value>}`. + */ + Return, }; - -namespace js { - class Breakpoint; class DebuggerMemory; class ScriptedOnStepHandler; class ScriptedOnPopHandler; class WasmInstanceObject; typedef HashSet<ReadBarrieredGlobalObject, MovableCellHasher<ReadBarrieredGlobalObject>, @@ -521,87 +559,93 @@ class Debugger : private mozilla::Linked class ObjectQuery; MOZ_MUST_USE bool addDebuggeeGlobal(JSContext* cx, Handle<GlobalObject*> obj); void removeDebuggeeGlobal(FreeOp* fop, GlobalObject* global, WeakGlobalObjectSet::Enum* debugEnum); /* * Report and clear the pending exception on ac.context, if any, and return - * JSTRAP_ERROR. + * ResumeMode::Terminate. */ - JSTrapStatus reportUncaughtException(mozilla::Maybe<AutoCompartment>& ac); + ResumeMode reportUncaughtException(mozilla::Maybe<AutoCompartment>& ac); /* * Cope with an error or exception in a debugger hook. * * If callHook is true, then call the uncaughtExceptionHook, if any. If, in * addition, vp is given, then parse the value returned by * uncaughtExceptionHook as a resumption value. * * If there is no uncaughtExceptionHook, or if it fails, report and clear - * the pending exception on ac.context and return JSTRAP_ERROR. + * the pending exception on ac.context and return ResumeMode::Terminate. * * This always calls ac.leave(); ac is a parameter because this method must * do some things in the debugger compartment and some things in the * debuggee compartment. */ - JSTrapStatus handleUncaughtException(mozilla::Maybe<AutoCompartment>& ac); - JSTrapStatus handleUncaughtException(mozilla::Maybe<AutoCompartment>& ac, - MutableHandleValue vp, - const mozilla::Maybe<HandleValue>& thisVForCheck = mozilla::Nothing(), - AbstractFramePtr frame = NullFramePtr()); + ResumeMode handleUncaughtException(mozilla::Maybe<AutoCompartment>& ac); + ResumeMode handleUncaughtException(mozilla::Maybe<AutoCompartment>& ac, + MutableHandleValue vp, + const mozilla::Maybe<HandleValue>& thisVForCheck = mozilla::Nothing(), + AbstractFramePtr frame = NullFramePtr()); - JSTrapStatus handleUncaughtExceptionHelper(mozilla::Maybe<AutoCompartment>& ac, - MutableHandleValue* vp, - const mozilla::Maybe<HandleValue>& thisVForCheck, - AbstractFramePtr frame); + ResumeMode handleUncaughtExceptionHelper(mozilla::Maybe<AutoCompartment>& ac, + MutableHandleValue* vp, + const mozilla::Maybe<HandleValue>& thisVForCheck, + AbstractFramePtr frame); /* * Handle the result of a hook that is expected to return a resumption - * value <https://wiki.mozilla.org/Debugger#Resumption_Values>. This is called - * when we return from a debugging hook to debuggee code. The interpreter wants - * a (JSTrapStatus, Value) pair telling it how to proceed. + * value <https://wiki.mozilla.org/Debugger#Resumption_Values>. This is + * called when we return from a debugging hook to debuggee code. The + * interpreter wants a (ResumeMode, Value) pair telling it how to proceed. * * Precondition: ac is entered. We are in the debugger compartment. * * Postcondition: This called ac.leave(). See handleUncaughtException. * - * If ok is false, the hook failed. If an exception is pending in + * If `success` is false, the hook failed. If an exception is pending in * ac.context(), return handleUncaughtException(ac, vp, callhook). - * Otherwise just return JSTRAP_ERROR. + * Otherwise just return ResumeMode::Terminate. + * + * If `success` is true, there must be no exception pending in ac.context(). + * `rv` may be: * - * If ok is true, there must be no exception pending in ac.context(). rv may be: - * undefined - Return JSTRAP_CONTINUE to continue execution normally. + * undefined - Return `ResumeMode::Continue` to continue execution + * normally. + * * {return: value} or {throw: value} - Call unwrapDebuggeeValue to - * unwrap value. Store the result in *vp and return JSTRAP_RETURN - * or JSTRAP_THROW. The interpreter will force the current frame to - * return or throw an exception. - * null - Return JSTRAP_ERROR to terminate the debuggee with an - * uncatchable error. + * unwrap `value`. Store the result in `*vp` and return + * `ResumeMode::Return` or `ResumeMode::Throw`. The interpreter + * will force the current frame to return or throw an exception. + * + * null - Return `ResumeMode::Terminate` to terminate the debuggee with + * an uncatchable error. + * * anything else - Make a new TypeError the pending exception and * return handleUncaughtException(ac, vp, callHook). */ - JSTrapStatus processHandlerResult(mozilla::Maybe<AutoCompartment>& ac, bool OK, const Value& rv, - AbstractFramePtr frame, jsbytecode* pc, MutableHandleValue vp); + ResumeMode processHandlerResult(mozilla::Maybe<AutoCompartment>& ac, bool success, const Value& rv, + AbstractFramePtr frame, jsbytecode* pc, MutableHandleValue vp); - JSTrapStatus processParsedHandlerResult(mozilla::Maybe<AutoCompartment>& ac, - AbstractFramePtr frame, jsbytecode* pc, - bool success, JSTrapStatus status, - MutableHandleValue vp); + ResumeMode processParsedHandlerResult(mozilla::Maybe<AutoCompartment>& ac, + AbstractFramePtr frame, jsbytecode* pc, + bool success, ResumeMode resumeMode, + MutableHandleValue vp); - JSTrapStatus processParsedHandlerResultHelper(mozilla::Maybe<AutoCompartment>& ac, - AbstractFramePtr frame, - const mozilla::Maybe<HandleValue>& maybeThisv, - bool success, JSTrapStatus status, - MutableHandleValue vp); + ResumeMode processParsedHandlerResultHelper(mozilla::Maybe<AutoCompartment>& ac, + AbstractFramePtr frame, + const mozilla::Maybe<HandleValue>& maybeThisv, + bool success, ResumeMode resumeMode, + MutableHandleValue vp); bool processResumptionValue(mozilla::Maybe<AutoCompartment>& ac, AbstractFramePtr frame, const mozilla::Maybe<HandleValue>& maybeThis, HandleValue rval, - JSTrapStatus& statusp, MutableHandleValue vp); + ResumeMode& resumeMode, MutableHandleValue vp); GlobalObject* unwrapDebuggeeArgument(JSContext* cx, const Value& v); static void traceObject(JSTracer* trc, JSObject* obj); void trace(JSTracer* trc); friend struct js::GCManagedDeletePolicy<Debugger>; @@ -722,40 +766,40 @@ class Debugger : private mozilla::Linked MOZ_MUST_USE bool updateObservesCoverageOnDebuggees(JSContext* cx, IsObserving observing); void updateObservesAsmJSOnDebuggees(IsObserving observing); void updateObservesBinarySourceDebuggees(IsObserving observing); JSObject* getHook(Hook hook) const; bool hasAnyLiveHooks(JSRuntime* rt) const; static MOZ_MUST_USE bool slowPathCheckNoExecute(JSContext* cx, HandleScript script); - static JSTrapStatus slowPathOnEnterFrame(JSContext* cx, AbstractFramePtr frame); + static ResumeMode slowPathOnEnterFrame(JSContext* cx, AbstractFramePtr frame); static MOZ_MUST_USE bool slowPathOnLeaveFrame(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc, bool ok); - static JSTrapStatus slowPathOnDebuggerStatement(JSContext* cx, AbstractFramePtr frame); - static JSTrapStatus slowPathOnExceptionUnwind(JSContext* cx, AbstractFramePtr frame); + static ResumeMode slowPathOnDebuggerStatement(JSContext* cx, AbstractFramePtr frame); + static ResumeMode slowPathOnExceptionUnwind(JSContext* cx, AbstractFramePtr frame); static void slowPathOnNewScript(JSContext* cx, HandleScript script); static void slowPathOnNewWasmInstance(JSContext* cx, Handle<WasmInstanceObject*> wasmInstance); static void slowPathOnNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global); static MOZ_MUST_USE bool slowPathOnLogAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame frame, mozilla::TimeStamp when, GlobalObject::DebuggerVector& dbgs); static void slowPathPromiseHook(JSContext* cx, Hook hook, Handle<PromiseObject*> promise); template <typename HookIsEnabledFun /* bool (Debugger*) */, - typename FireHookFun /* JSTrapStatus (Debugger*) */> - static JSTrapStatus dispatchHook(JSContext* cx, HookIsEnabledFun hookIsEnabled, - FireHookFun fireHook); + typename FireHookFun /* ResumeMode (Debugger*) */> + static ResumeMode dispatchHook(JSContext* cx, HookIsEnabledFun hookIsEnabled, + FireHookFun fireHook); - JSTrapStatus fireDebuggerStatement(JSContext* cx, MutableHandleValue vp); - JSTrapStatus fireExceptionUnwind(JSContext* cx, MutableHandleValue vp); - JSTrapStatus fireEnterFrame(JSContext* cx, MutableHandleValue vp); - JSTrapStatus fireNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global, MutableHandleValue vp); - JSTrapStatus firePromiseHook(JSContext* cx, Hook hook, HandleObject promise, MutableHandleValue vp); + ResumeMode fireDebuggerStatement(JSContext* cx, MutableHandleValue vp); + ResumeMode fireExceptionUnwind(JSContext* cx, MutableHandleValue vp); + ResumeMode fireEnterFrame(JSContext* cx, MutableHandleValue vp); + ResumeMode fireNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global, MutableHandleValue vp); + ResumeMode firePromiseHook(JSContext* cx, Hook hook, HandleObject promise, MutableHandleValue vp); NativeObject* newVariantWrapper(JSContext* cx, Handle<DebuggerScriptReferent> referent) { return newDebuggerScript(cx, referent); } NativeObject* newVariantWrapper(JSContext* cx, Handle<DebuggerSourceReferent> referent) { return newDebuggerSource(cx, referent); } @@ -858,58 +902,37 @@ class Debugger : private mozilla::Linked #ifdef DEBUG static bool isDebuggerCrossCompartmentEdge(JSObject* obj, const js::gc::Cell* cell); #endif // Checks it the current compartment is allowed to execute code. static inline MOZ_MUST_USE bool checkNoExecute(JSContext* cx, HandleScript script); /* - * JSTrapStatus Overview - * --------------------- - * - * The |onEnterFrame|, |onDebuggerStatement|, and |onExceptionUnwind| - * methods below return a JSTrapStatus code that indicates how execution - * should proceed: - * - * - JSTRAP_CONTINUE: Continue execution normally. - * - * - JSTRAP_THROW: Throw an exception. The method has set |cx|'s - * pending exception to the value to be thrown. - * - * - JSTRAP_ERROR: Terminate execution (as is done when a script is terminated - * for running too long). The method has cleared |cx|'s pending - * exception. - * - * - JSTRAP_RETURN: Return from the new frame immediately. The method has - * set the youngest JS frame's return value appropriately. - */ - - /* * Announce to the debugger that the context has entered a new JavaScript * frame, |frame|. Call whatever hooks have been registered to observe new * frames. */ - static inline JSTrapStatus onEnterFrame(JSContext* cx, AbstractFramePtr frame); + static inline ResumeMode onEnterFrame(JSContext* cx, AbstractFramePtr frame); /* * Announce to the debugger a |debugger;| statement on has been * encountered on the youngest JS frame on |cx|. Call whatever hooks have * been registered to observe this. * * Note that this method is called for all |debugger;| statements, * regardless of the frame's debuggee-ness. */ - static inline JSTrapStatus onDebuggerStatement(JSContext* cx, AbstractFramePtr frame); + static inline ResumeMode onDebuggerStatement(JSContext* cx, AbstractFramePtr frame); /* * Announce to the debugger that an exception has been thrown and propagated * to |frame|. Call whatever hooks have been registered to observe this. */ - static inline JSTrapStatus onExceptionUnwind(JSContext* cx, AbstractFramePtr frame); + static inline ResumeMode onExceptionUnwind(JSContext* cx, AbstractFramePtr frame); /* * Announce to the debugger that the thread has exited a JavaScript frame, |frame|. * If |ok| is true, the frame is returning normally; if |ok| is false, the frame * is throwing an exception or terminating. * * Change cx's current exception and |frame|'s return value to reflect the changes * in behavior the hooks request, if any. Return the new error/success value. @@ -923,18 +946,18 @@ class Debugger : private mozilla::Linked static inline MOZ_MUST_USE bool onLeaveFrame(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc, bool ok); static inline void onNewScript(JSContext* cx, HandleScript script); static inline void onNewWasmInstance(JSContext* cx, Handle<WasmInstanceObject*> wasmInstance); static inline void onNewGlobalObject(JSContext* cx, Handle<GlobalObject*> global); static inline MOZ_MUST_USE bool onLogAllocationSite(JSContext* cx, JSObject* obj, HandleSavedFrame frame, mozilla::TimeStamp when); - static JSTrapStatus onTrap(JSContext* cx, MutableHandleValue vp); - static JSTrapStatus onSingleStep(JSContext* cx, MutableHandleValue vp); + static ResumeMode onTrap(JSContext* cx, MutableHandleValue vp); + static ResumeMode onSingleStep(JSContext* cx, MutableHandleValue vp); static MOZ_MUST_USE bool handleBaselineOsr(JSContext* cx, InterpreterFrame* from, jit::BaselineFrame* to); static MOZ_MUST_USE bool handleIonBailout(JSContext* cx, jit::RematerializedFrame* from, jit::BaselineFrame* to); static void handleUnrecoverableIonBailoutError(JSContext* cx, jit::RematerializedFrame* frame); static void propagateForcedReturn(JSContext* cx, AbstractFramePtr frame, HandleValue rval); static bool hasLiveHook(GlobalObject* global, Hook which); static bool inFrameMaps(AbstractFramePtr frame); @@ -1051,31 +1074,31 @@ class Debugger : private mozilla::Linked MutableHandleValue vp) { return getScriptFrameWithIter(cx, iter.abstractFramePtr(), &iter, vp); } MOZ_MUST_USE bool getScriptFrame(JSContext* cx, const FrameIter& iter, MutableHandleDebuggerFrame result); /* - * Set |*status| and |*value| to a (JSTrapStatus, Value) pair reflecting a + * Set |*resumeMode| and |*value| to a (ResumeMode, Value) pair reflecting a * standard SpiderMonkey call state: a boolean success value |ok|, a return * value |rv|, and a context |cx| that may or may not have an exception set. * If an exception was pending on |cx|, it is cleared (and |ok| is asserted * to be false). */ static void resultToCompletion(JSContext* cx, bool ok, const Value& rv, - JSTrapStatus* status, MutableHandleValue value); + ResumeMode* resumeMode, MutableHandleValue value); /* - * Set |*result| to a JavaScript completion value corresponding to |status| + * Set |*result| to a JavaScript completion value corresponding to |resumeMode| * and |value|. |value| should be the return value or exception value, not * wrapped as a debuggee value. |cx| must be in the debugger compartment. */ - MOZ_MUST_USE bool newCompletionValue(JSContext* cx, JSTrapStatus status, const Value& value, + MOZ_MUST_USE bool newCompletionValue(JSContext* cx, ResumeMode resumeMode, const Value& value, MutableHandleValue result); /* * Precondition: we are in the debuggee compartment (ac is entered) and ok * is true if the operation in the debuggee compartment succeeded, false on * error or exception. * * Postcondition: we are in the debugger compartment, having called @@ -1261,59 +1284,59 @@ class DebuggerArguments : public NativeO /* * An OnStepHandler represents a handler function that is called when a small * amount of progress is made in a frame. */ struct OnStepHandler : Handler { /* * If we have made a small amount of progress in a frame, this method is * called with the frame as argument. If succesful, this method should - * return true, with `statusp` and `vp` set to a resumption value + * return true, with `resumeMode` and `vp` set to a resumption value * specifiying how execution should continue. */ - virtual bool onStep(JSContext* cx, HandleDebuggerFrame frame, JSTrapStatus& statusp, + virtual bool onStep(JSContext* cx, HandleDebuggerFrame frame, ResumeMode& resumeMode, MutableHandleValue vp) = 0; }; class ScriptedOnStepHandler final : public OnStepHandler { public: explicit ScriptedOnStepHandler(JSObject* object); virtual JSObject* object() const override; virtual void drop() override; virtual void trace(JSTracer* tracer) override; - virtual bool onStep(JSContext* cx, HandleDebuggerFrame frame, JSTrapStatus& statusp, + virtual bool onStep(JSContext* cx, HandleDebuggerFrame frame, ResumeMode& resumeMode, MutableHandleValue vp) override; private: HeapPtr<JSObject*> object_; }; /* * An OnPopHandler represents a handler function that is called just before a * frame is popped. */ struct OnPopHandler : Handler { /* * If a frame is about the be popped, this method is called with the frame - * as argument, and `statusp` and `vp` set to a completion value specifying + * as argument, and `resumeMode` and `vp` set to a completion value specifying * how this frame's execution completed. If successful, this method should - * return true, with `statusp` and `vp` set to a resumption value specifying + * return true, with `resumeMode` and `vp` set to a resumption value specifying * how execution should continue. */ - virtual bool onPop(JSContext* cx, HandleDebuggerFrame frame, JSTrapStatus& statusp, + virtual bool onPop(JSContext* cx, HandleDebuggerFrame frame, ResumeMode& resumeMode, MutableHandleValue vp) = 0; }; class ScriptedOnPopHandler final : public OnPopHandler { public: explicit ScriptedOnPopHandler(JSObject* object); virtual JSObject* object() const override; virtual void drop() override; virtual void trace(JSTracer* tracer) override; - virtual bool onPop(JSContext* cx, HandleDebuggerFrame frame, JSTrapStatus& statusp, + virtual bool onPop(JSContext* cx, HandleDebuggerFrame frame, ResumeMode& resumeMode, MutableHandleValue vp) override; private: HeapPtr<JSObject*> object_; }; class DebuggerFrame : public NativeObject { @@ -1350,17 +1373,17 @@ class DebuggerFrame : public NativeObjec MutableHandleValue result); static DebuggerFrameType getType(HandleDebuggerFrame frame); static DebuggerFrameImplementation getImplementation(HandleDebuggerFrame frame); static MOZ_MUST_USE bool setOnStepHandler(JSContext* cx, HandleDebuggerFrame frame, OnStepHandler* handler); static MOZ_MUST_USE bool eval(JSContext* cx, HandleDebuggerFrame frame, mozilla::Range<const char16_t> chars, HandleObject bindings, - const EvalOptions& options, JSTrapStatus& status, + const EvalOptions& options, ResumeMode& resumeMode, MutableHandleValue value); bool isLive() const; OnStepHandler* onStepHandler() const; OnPopHandler* onPopHandler() const; void setOnPopHandler(OnPopHandler* handler); private: @@ -1466,17 +1489,17 @@ class DebuggerObject : public NativeObje static MOZ_MUST_USE bool call(JSContext* cx, HandleDebuggerObject object, HandleValue thisv, Handle<ValueVector> args, MutableHandleValue result); static MOZ_MUST_USE bool forceLexicalInitializationByName(JSContext* cx, HandleDebuggerObject object, HandleId id, bool& result); static MOZ_MUST_USE bool executeInGlobal(JSContext* cx, HandleDebuggerObject object, mozilla::Range<const char16_t> chars, HandleObject bindings, const EvalOptions& options, - JSTrapStatus& status, MutableHandleValue value); + ResumeMode& resumeMode, MutableHandleValue value); static MOZ_MUST_USE bool makeDebuggeeValue(JSContext* cx, HandleDebuggerObject object, HandleValue value, MutableHandleValue result); static MOZ_MUST_USE bool unsafeDereference(JSContext* cx, HandleDebuggerObject object, MutableHandleObject result); static MOZ_MUST_USE bool unwrap(JSContext* cx, HandleDebuggerObject object, MutableHandleDebuggerObject result); // Infallible properties
--- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1329,33 +1329,33 @@ HandleError(JSContext* cx, InterpreterRe EnvironmentIter ei(cx, regs.fp(), regs.pc); bool ok = false; again: if (cx->isExceptionPending()) { /* Call debugger throw hooks. */ if (!cx->isClosingGenerator()) { - JSTrapStatus status = Debugger::onExceptionUnwind(cx, regs.fp()); - switch (status) { - case JSTRAP_ERROR: + ResumeMode mode = Debugger::onExceptionUnwind(cx, regs.fp()); + switch (mode) { + case ResumeMode::Terminate: goto again; - case JSTRAP_CONTINUE: - case JSTRAP_THROW: + case ResumeMode::Continue: + case ResumeMode::Throw: break; - case JSTRAP_RETURN: + case ResumeMode::Return: UnwindIteratorsForUncatchableException(cx, regs); if (!ForcedReturn(cx, regs)) return ErrorReturnContinuation; return SuccessfulReturnContinuation; default: - MOZ_CRASH("Bad Debugger::onExceptionUnwind status"); + MOZ_CRASH("bad Debugger::onExceptionUnwind resume mode"); } } HandleErrorContinuation res = ProcessTryNotes(cx, ei, regs); switch (res) { case SuccessfulReturnContinuation: break; case ErrorReturnContinuation: @@ -1903,27 +1903,27 @@ Interpret(JSContext* cx, RunState& state /* State communicated between non-local jumps: */ bool interpReturnOK; bool frameHalfInitialized; if (!activation.entryFrame()->prologue(cx)) goto prologue_error; switch (Debugger::onEnterFrame(cx, activation.entryFrame())) { - case JSTRAP_CONTINUE: + case ResumeMode::Continue: break; - case JSTRAP_RETURN: + case ResumeMode::Return: if (!ForcedReturn(cx, REGS)) goto error; goto successful_return_continuation; - case JSTRAP_THROW: - case JSTRAP_ERROR: + case ResumeMode::Throw: + case ResumeMode::Terminate: goto error; default: - MOZ_CRASH("bad Debugger::onEnterFrame status"); + MOZ_CRASH("bad Debugger::onEnterFrame resume mode"); } // Increment the coverage for the main entry point. INIT_COVERAGE(); COUNT_COVERAGE_MAIN(); // Enter the interpreter loop starting at the current pc. ADVANCE_AND_DISPATCH(0); @@ -1938,57 +1938,56 @@ CASE(EnableInterruptsPseudoOpcode) if (!script->hasScriptCounts() && cx->compartment()->collectCoverageForDebug()) { if (!script->initScriptCounts(cx)) goto error; } if (script->isDebuggee()) { if (script->stepModeEnabled()) { RootedValue rval(cx); - JSTrapStatus status = JSTRAP_CONTINUE; - status = Debugger::onSingleStep(cx, &rval); - switch (status) { - case JSTRAP_ERROR: + ResumeMode mode = Debugger::onSingleStep(cx, &rval); + switch (mode) { + case ResumeMode::Terminate: goto error; - case JSTRAP_CONTINUE: + case ResumeMode::Continue: break; - case JSTRAP_RETURN: + case ResumeMode::Return: REGS.fp()->setReturnValue(rval); if (!ForcedReturn(cx, REGS)) goto error; goto successful_return_continuation; - case JSTRAP_THROW: + case ResumeMode::Throw: cx->setPendingException(rval); goto error; default:; } moreInterrupts = true; } if (script->hasAnyBreakpointsOrStepMode()) moreInterrupts = true; if (script->hasBreakpointsAt(REGS.pc)) { RootedValue rval(cx); - JSTrapStatus status = Debugger::onTrap(cx, &rval); - switch (status) { - case JSTRAP_ERROR: + ResumeMode mode = Debugger::onTrap(cx, &rval); + switch (mode) { + case ResumeMode::Terminate: goto error; - case JSTRAP_RETURN: + case ResumeMode::Return: REGS.fp()->setReturnValue(rval); if (!ForcedReturn(cx, REGS)) goto error; goto successful_return_continuation; - case JSTRAP_THROW: + case ResumeMode::Throw: cx->setPendingException(rval); goto error; default: break; } - MOZ_ASSERT(status == JSTRAP_CONTINUE); + MOZ_ASSERT(mode == ResumeMode::Continue); MOZ_ASSERT(rval.isInt32() && rval.toInt32() == op); } } MOZ_ASSERT(activation.opMask() == EnableInterruptsPseudoOpcode); if (!moreInterrupts) activation.clearInterruptsMask(); @@ -3138,27 +3137,27 @@ CASE(JSOP_FUNCALL) TraceLogStartEvent(logger, event); TraceLogStartEvent(logger, TraceLogger_Interpreter); } if (!REGS.fp()->prologue(cx)) goto prologue_error; switch (Debugger::onEnterFrame(cx, REGS.fp())) { - case JSTRAP_CONTINUE: + case ResumeMode::Continue: break; - case JSTRAP_RETURN: + case ResumeMode::Return: if (!ForcedReturn(cx, REGS)) goto error; goto successful_return_continuation; - case JSTRAP_THROW: - case JSTRAP_ERROR: + case ResumeMode::Throw: + case ResumeMode::Terminate: goto error; default: - MOZ_CRASH("bad Debugger::onEnterFrame status"); + MOZ_CRASH("bad Debugger::onEnterFrame resume mode"); } // Increment the coverage for the main entry point. INIT_COVERAGE(); COUNT_COVERAGE_MAIN(); /* Load first op and dispatch it (safe since JSOP_RETRVAL). */ ADVANCE_AND_DISPATCH(0); @@ -3939,25 +3938,25 @@ CASE(JSOP_INSTANCEOF) REGS.sp[-1].setBoolean(cond); } END_CASE(JSOP_INSTANCEOF) CASE(JSOP_DEBUGGER) { RootedValue rval(cx); switch (Debugger::onDebuggerStatement(cx, REGS.fp())) { - case JSTRAP_ERROR: + case ResumeMode::Terminate: goto error; - case JSTRAP_CONTINUE: + case ResumeMode::Continue: break; - case JSTRAP_RETURN: + case ResumeMode::Return: if (!ForcedReturn(cx, REGS)) goto error; goto successful_return_continuation; - case JSTRAP_THROW: + case ResumeMode::Throw: goto error; default:; } } END_CASE(JSOP_DEBUGGER) CASE(JSOP_PUSHLEXICALENV) {
--- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -548,25 +548,25 @@ InvokeInterruptCallback(JSContext* cx) if (cx->compartment()->isDebuggee()) { ScriptFrameIter iter(cx); if (!iter.done() && cx->compartment() == iter.compartment() && iter.script()->stepModeEnabled()) { RootedValue rval(cx); switch (Debugger::onSingleStep(cx, &rval)) { - case JSTRAP_ERROR: + case ResumeMode::Terminate: return false; - case JSTRAP_CONTINUE: + case ResumeMode::Continue: return true; - case JSTRAP_RETURN: + case ResumeMode::Return: // See note in Debugger::propagateForcedReturn. Debugger::propagateForcedReturn(cx, iter.abstractFramePtr(), rval); return false; - case JSTRAP_THROW: + case ResumeMode::Throw: cx->setPendingException(rval); return false; default:; } } } return true;
--- a/js/src/wasm/WasmBuiltins.cpp +++ b/js/src/wasm/WasmBuiltins.cpp @@ -88,56 +88,55 @@ WasmHandleDebugTrap() fp = fp->callerFP; DebugFrame* debugFrame = DebugFrame::from(fp); if (site->kind() == CallSite::EnterFrame) { if (!instance->enterFrameTrapsEnabled()) return true; debugFrame->setIsDebuggee(); debugFrame->observe(cx); - // TODO call onEnterFrame - JSTrapStatus status = Debugger::onEnterFrame(cx, debugFrame); - if (status == JSTRAP_RETURN) { - // Ignoring forced return (JSTRAP_RETURN) -- changing code execution + ResumeMode mode = Debugger::onEnterFrame(cx, debugFrame); + if (mode == ResumeMode::Return) { + // Ignoring forced return (ResumeMode::Return) -- changing code execution // order is not yet implemented in the wasm baseline. - // TODO properly handle JSTRAP_RETURN and resume wasm execution. + // TODO properly handle ResumeMode::Return and resume wasm execution. JS_ReportErrorASCII(cx, "Unexpected resumption value from onEnterFrame"); return false; } - return status == JSTRAP_CONTINUE; + return mode == ResumeMode::Continue; } if (site->kind() == CallSite::LeaveFrame) { debugFrame->updateReturnJSValue(); bool ok = Debugger::onLeaveFrame(cx, debugFrame, nullptr, true); debugFrame->leave(cx); return ok; } DebugState& debug = instance->debug(); MOZ_ASSERT(debug.hasBreakpointTrapAtOffset(site->lineOrBytecode())); if (debug.stepModeEnabled(debugFrame->funcIndex())) { RootedValue result(cx, UndefinedValue()); - JSTrapStatus status = Debugger::onSingleStep(cx, &result); - if (status == JSTRAP_RETURN) { - // TODO properly handle JSTRAP_RETURN. + ResumeMode mode = Debugger::onSingleStep(cx, &result); + if (mode == ResumeMode::Return) { + // TODO properly handle ResumeMode::Return. JS_ReportErrorASCII(cx, "Unexpected resumption value from onSingleStep"); return false; } - if (status != JSTRAP_CONTINUE) + if (mode != ResumeMode::Continue) return false; } if (debug.hasBreakpointSite(site->lineOrBytecode())) { RootedValue result(cx, UndefinedValue()); - JSTrapStatus status = Debugger::onTrap(cx, &result); - if (status == JSTRAP_RETURN) { - // TODO properly handle JSTRAP_RETURN. + ResumeMode mode = Debugger::onTrap(cx, &result); + if (mode == ResumeMode::Return) { + // TODO properly handle ResumeMode::Return. JS_ReportErrorASCII(cx, "Unexpected resumption value from breakpoint handler"); return false; } - if (status != JSTRAP_CONTINUE) + if (mode != ResumeMode::Continue) return false; } return true; } // Unwind the entire activation in response to a thrown exception. This function // is responsible for notifying the debugger of each unwound frame. The return // value is the new stack address which the calling stub will set to the sp @@ -170,24 +169,24 @@ wasm::HandleThrow(JSContext* cx, WasmFra for (; !iter.done(); ++iter) { if (!iter.debugEnabled()) continue; DebugFrame* frame = iter.debugFrame(); frame->clearReturnJSValue(); - // Assume JSTRAP_ERROR status if no exception is pending -- + // Assume ResumeMode::Terminate if no exception is pending -- // no onExceptionUnwind handlers must be fired. if (cx->isExceptionPending()) { - JSTrapStatus status = Debugger::onExceptionUnwind(cx, frame); - if (status == JSTRAP_RETURN) { + ResumeMode mode = Debugger::onExceptionUnwind(cx, frame); + if (mode == ResumeMode::Return) { // Unexpected trap return -- raising error since throw recovery // is not yet implemented in the wasm baseline. - // TODO properly handle JSTRAP_RETURN and resume wasm execution. + // TODO properly handle ResumeMode::Return and resume wasm execution. JS_ReportErrorASCII(cx, "Unexpected resumption value from onExceptionUnwind"); } } bool ok = Debugger::onLeaveFrame(cx, frame, nullptr, false); if (ok) { // Unexpected success from the handler onLeaveFrame -- raising error // since throw recovery is not yet implemented in the wasm baseline.