Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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++);
    }
}
Example #4
0
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);
}
Example #5
0
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);
}
Example #6
0
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++);
}
Example #7
0
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);
}
Example #8
0
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;
}
Example #9
0
// 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());
}