JSTrapStatus js::ScriptDebugPrologue(JSContext *cx, AbstractFramePtr frame) { JS_ASSERT_IF(frame.isStackFrame(), frame.asStackFrame() == cx->fp()); if (frame.isFramePushedByExecute()) { if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook) frame.setHookData(hook(cx, Jsvalify(frame.asStackFrame()), true, 0, cx->runtime->debugHooks.executeHookData)); } else { if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook) frame.setHookData(hook(cx, Jsvalify(frame.asStackFrame()), true, 0, cx->runtime->debugHooks.callHookData)); } Value rval; JSTrapStatus status = Debugger::onEnterFrame(cx, &rval); switch (status) { case JSTRAP_CONTINUE: break; case JSTRAP_THROW: cx->setPendingException(rval); break; case JSTRAP_ERROR: cx->clearPendingException(); break; case JSTRAP_RETURN: frame.setReturnValue(rval); break; default: JS_NOT_REACHED("bad Debugger::onEnterFrame JSTrapStatus value"); } return status; }
JSObject * JSAbstractFramePtr::callObject(JSContext *cx) { AbstractFramePtr frame = Valueify(*this); JS_ASSERT_IF(frame.isStackFrame(), cx->stack.space().containsSlow(frame.asStackFrame())); if (!frame.isFunctionFrame()) return NULL; JSObject *o = GetDebugScopeForFrame(cx, frame); /* * Given that fp is a function frame and GetDebugScopeForFrame always fills * in missing scopes, we can expect to find fp's CallObject on 'o'. Note: * - GetDebugScopeForFrame wraps every ScopeObject (missing or not) with * a DebugScopeObject proxy. * - If fp is an eval-in-function, then fp has no callobj of its own and * JS_GetFrameCallObject will return the innermost function's callobj. */ while (o) { ScopeObject &scope = o->asDebugScope().scope(); if (scope.isCall()) return o; o = o->enclosingScope(); } return NULL; }
static void CopyStackFrameArguments(const AbstractFramePtr frame, HeapValue *dst, unsigned totalArgs) { JS_ASSERT_IF(frame.isStackFrame(), !frame.asStackFrame()->runningInIon()); unsigned numActuals = frame.numActualArgs(); unsigned numFormals = frame.callee()->nargs; JS_ASSERT(numActuals <= totalArgs); JS_ASSERT(numFormals <= totalArgs); JS_ASSERT(Max(numActuals, numFormals) == totalArgs); /* Copy formal arguments. */ Value *src = frame.formals(); Value *end = src + numFormals; while (src != end) (dst++)->init(*src++); /* Copy actual argument which are not contignous. */ if (numFormals < numActuals) { src = frame.actuals() + numFormals; end = src + (numActuals - numFormals); while (src != end) (dst++)->init(*src++); } }
bool js::ScriptDebugEpilogue(JSContext *cx, AbstractFramePtr frame, bool okArg) { JS_ASSERT_IF(frame.isStackFrame(), frame.asStackFrame() == cx->fp()); JSBool ok = okArg; if (void *hookData = frame.maybeHookData()) { if (frame.isFramePushedByExecute()) { if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook) hook(cx, Jsvalify(frame.asStackFrame()), false, &ok, hookData); } else { if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook) hook(cx, Jsvalify(frame.asStackFrame()), false, &ok, hookData); } } return Debugger::onLeaveFrame(cx, ok); }
JSObject * JSAbstractFramePtr::scopeChain(JSContext *cx) { AbstractFramePtr frame = Valueify(*this); JS_ASSERT_IF(frame.isStackFrame(), cx->stack.space().containsSlow(frame.asStackFrame())); RootedObject scopeChain(cx, frame.scopeChain()); AutoCompartment ac(cx, scopeChain); return GetDebugScopeForFrame(cx, frame); }
static void CopyStackFrameArguments(const AbstractFramePtr frame, HeapValue *dst, unsigned totalArgs) { JS_ASSERT_IF(frame.isStackFrame(), !frame.asStackFrame()->runningInJit()); JS_ASSERT(Max(frame.numActualArgs(), frame.numFormalArgs()) == totalArgs); /* Copy arguments. */ Value *src = frame.argv(); Value *end = src + totalArgs; while (src != end) (dst++)->init(*src++); }
bool js::ScriptDebugEpilogue(JSContext *cx, AbstractFramePtr frame, bool okArg) { JS_ASSERT_IF(frame.isStackFrame(), frame.asStackFrame() == cx->fp()); JSBool ok = okArg; // We don't add hook data for self-hosted scripts, so we don't need to check for them, here. if (void *hookData = frame.maybeHookData()) { if (frame.isFramePushedByExecute()) { if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook) hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame), false, &ok, hookData); } else { if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook) hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame), false, &ok, hookData); } } return Debugger::onLeaveFrame(cx, frame, ok); }
JSTrapStatus js::ScriptDebugPrologue(JSContext *cx, AbstractFramePtr frame, jsbytecode *pc) { JS_ASSERT_IF(frame.isStackFrame(), frame.asStackFrame() == cx->interpreterFrame()); if (!frame.script()->selfHosted()) { JSAbstractFramePtr jsframe(frame.raw(), pc); if (frame.isFramePushedByExecute()) { if (JSInterpreterHook hook = cx->runtime()->debugHooks.executeHook) frame.setHookData(hook(cx, jsframe, IsTopFrameConstructing(cx, frame), true, 0, cx->runtime()->debugHooks.executeHookData)); } else { if (JSInterpreterHook hook = cx->runtime()->debugHooks.callHook) frame.setHookData(hook(cx, jsframe, IsTopFrameConstructing(cx, frame), true, 0, cx->runtime()->debugHooks.callHookData)); } } RootedValue rval(cx); JSTrapStatus status = Debugger::onEnterFrame(cx, frame, &rval); switch (status) { case JSTRAP_CONTINUE: break; case JSTRAP_THROW: cx->setPendingException(rval); break; case JSTRAP_ERROR: cx->clearPendingException(); break; case JSTRAP_RETURN: frame.setReturnValue(rval); break; default: MOZ_ASSUME_UNREACHABLE("bad Debugger::onEnterFrame JSTrapStatus value"); } return status; }
// Common code implementing direct and indirect eval. // // Evaluate call.argv[2], if it is a string, in the context of the given calling // frame, with the provided scope chain, with the semantics of either a direct // or indirect eval (see ES5 10.4.2). If this is an indirect eval, scopeobj // must be a global object. // // On success, store the completion value in call.rval and return true. static bool EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, AbstractFramePtr caller, HandleObject scopeobj) { JS_ASSERT((evalType == INDIRECT_EVAL) == !caller); JS_ASSERT_IF(evalType == INDIRECT_EVAL, scopeobj->isGlobal()); AssertInnerizedScopeChain(cx, *scopeobj); Rooted<GlobalObject*> scopeObjGlobal(cx, &scopeobj->global()); if (!GlobalObject::isRuntimeCodeGenEnabled(cx, scopeObjGlobal)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_EVAL); return false; } // ES5 15.1.2.1 step 1. if (args.length() < 1) { args.rval().setUndefined(); return true; } if (!args[0].isString()) { args.rval().set(args[0]); return true; } RootedString str(cx, args[0].toString()); // ES5 15.1.2.1 steps 2-8. // Per ES5, indirect eval runs in the global scope. (eval is specified this // way so that the compiler can make assumptions about what bindings may or // may not exist in the current frame if it doesn't see 'eval'.) unsigned staticLevel; RootedValue thisv(cx); if (evalType == DIRECT_EVAL) { JS_ASSERT_IF(caller.isStackFrame(), !caller.asStackFrame()->runningInIon()); staticLevel = caller.script()->staticLevel + 1; // Direct calls to eval are supposed to see the caller's |this|. If we // haven't wrapped that yet, do so now, before we make a copy of it for // the eval code to use. if (!ComputeThis(cx, caller)) return false; thisv = caller.thisValue(); } else { JS_ASSERT(args.callee().global() == *scopeobj); staticLevel = 0; // Use the global as 'this', modulo outerization. JSObject *thisobj = JSObject::thisObject(cx, scopeobj); if (!thisobj) return false; thisv = ObjectValue(*thisobj); } Rooted<JSStableString*> stableStr(cx, str->ensureStable(cx)); if (!stableStr) return false; StableCharPtr chars = stableStr->chars(); size_t length = stableStr->length(); JSPrincipals *principals = PrincipalsForCompiledCode(args, cx); JSScript *callerScript = caller ? caller.script() : NULL; EvalJSONResult ejr = TryEvalJSON(cx, callerScript, chars, length, args.rval()); if (ejr != EvalJSON_NotJSON) return ejr == EvalJSON_Success; EvalScriptGuard esg(cx); if (evalType == DIRECT_EVAL && caller.isNonEvalFunctionFrame()) esg.lookupInEvalCache(stableStr, caller.fun(), staticLevel); if (!esg.foundScript()) { unsigned lineno; const char *filename; JSPrincipals *originPrincipals; CurrentScriptFileLineOrigin(cx, &filename, &lineno, &originPrincipals, evalType == DIRECT_EVAL ? CALLED_FROM_JSOP_EVAL : NOT_CALLED_FROM_JSOP_EVAL); CompileOptions options(cx); options.setFileAndLine(filename, lineno) .setCompileAndGo(true) .setNoScriptRval(false) .setPrincipals(principals) .setOriginPrincipals(originPrincipals); RootedScript callerScript(cx, caller ? caller.script() : NULL); UnrootedScript compiled = frontend::CompileScript(cx, scopeobj, callerScript, options, chars.get(), length, stableStr, staticLevel); if (!compiled) return false; esg.setNewScript(compiled); } return ExecuteKernel(cx, esg.script(), *scopeobj, thisv, ExecuteType(evalType), NullFramePtr() /* evalInFrame */, args.rval().address()); }