Example #1
0
bool
js::DirectEvalStringFromIon(JSContext* cx,
                            HandleObject scopeObj, HandleScript callerScript,
                            HandleValue newTargetValue, HandleString str,
                            jsbytecode* pc, MutableHandleValue vp)
{
    AssertInnerizedScopeChain(cx, *scopeObj);

    Rooted<GlobalObject*> scopeObjGlobal(cx, &scopeObj->global());
    if (!GlobalObject::isRuntimeCodeGenEnabled(cx, scopeObjGlobal)) {
        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_EVAL);
        return false;
    }

    // ES5 15.1.2.1 steps 2-8.

    RootedLinearString linearStr(cx, str->ensureLinear(cx));
    if (!linearStr)
        return false;

    EvalJSONResult ejr = TryEvalJSON(cx, linearStr, vp);
    if (ejr != EvalJSON_NotJSON)
        return ejr == EvalJSON_Success;

    EvalScriptGuard esg(cx);

    esg.lookupInEvalCache(linearStr, callerScript, pc);

    if (!esg.foundScript()) {
        RootedScript maybeScript(cx);
        const char* filename;
        unsigned lineno;
        bool mutedErrors;
        uint32_t pcOffset;
        DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
                                             &mutedErrors, CALLED_FROM_JSOP_EVAL);

        const char* introducerFilename = filename;
        if (maybeScript && maybeScript->scriptSource()->introducerFilename())
            introducerFilename = maybeScript->scriptSource()->introducerFilename();

        RootedObject enclosing(cx, callerScript->innermostStaticScope(pc));
        Rooted<StaticEvalScope*> staticScope(cx, StaticEvalScope::create(cx, enclosing));
        if (!staticScope)
            return false;

        CompileOptions options(cx);
        options.setIsRunOnce(true)
               .setForEval(true)
               .setNoScriptRval(false)
               .setMutedErrors(mutedErrors)
               .maybeMakeStrictMode(IsStrictEvalPC(pc));

        if (introducerFilename) {
            options.setFileAndLine(filename, 1);
            options.setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);
        } else {
            options.setFileAndLine("eval", 1);
            options.setIntroductionType("eval");
        }

        AutoStableStringChars linearChars(cx);
        if (!linearChars.initTwoByte(cx, linearStr))
            return false;

        const char16_t* chars = linearChars.twoByteRange().start().get();
        SourceBufferHolder::Ownership ownership = linearChars.maybeGiveOwnershipToCaller()
                                                  ? SourceBufferHolder::GiveOwnership
                                                  : SourceBufferHolder::NoOwnership;
        SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
        JSScript* compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
                                                     scopeObj, staticScope, callerScript,
                                                     options, srcBuf, linearStr);
        if (!compiled)
            return false;

        if (compiled->strict())
            staticScope->setStrict();

        esg.setNewScript(compiled);
    }

    return ExecuteKernel(cx, esg.script(), *scopeObj, newTargetValue,
                         NullFramePtr() /* evalInFrame */, vp.address());
}
Example #2
0
bool
js::DirectEvalStringFromIon(JSContext* cx,
                            HandleObject scopeobj, HandleScript callerScript,
                            HandleValue thisValue, HandleValue newTargetValue,
                            HandleString str, jsbytecode* pc, MutableHandleValue vp)
{
    AssertInnerizedScopeChain(cx, *scopeobj);

    Rooted<GlobalObject*> scopeObjGlobal(cx, &scopeobj->global());
    if (!GlobalObject::isRuntimeCodeGenEnabled(cx, scopeObjGlobal)) {
        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CSP_BLOCKED_EVAL);
        return false;
    }

    // ES5 15.1.2.1 steps 2-8.

    unsigned staticLevel = callerScript->staticLevel() + 1;

    RootedLinearString linearStr(cx, str->ensureLinear(cx));
    if (!linearStr)
        return false;

    EvalJSONResult ejr = TryEvalJSON(cx, linearStr, vp);
    if (ejr != EvalJSON_NotJSON)
        return ejr == EvalJSON_Success;

    EvalScriptGuard esg(cx);

    esg.lookupInEvalCache(linearStr, callerScript, pc);

    if (!esg.foundScript()) {
        RootedScript maybeScript(cx);
        const char* filename;
        unsigned lineno;
        bool mutedErrors;
        uint32_t pcOffset;
        DescribeScriptedCallerForCompilation(cx, &maybeScript, &filename, &lineno, &pcOffset,
                                             &mutedErrors, CALLED_FROM_JSOP_EVAL);

        const char* introducerFilename = filename;
        if (maybeScript && maybeScript->scriptSource()->introducerFilename())
            introducerFilename = maybeScript->scriptSource()->introducerFilename();

        RootedObject enclosing(cx, callerScript->innermostStaticScope(pc));
        Rooted<StaticEvalObject*> staticScope(cx, StaticEvalObject::create(cx, enclosing));
        if (!staticScope)
            return false;

        CompileOptions options(cx);
        options.setFileAndLine(filename, 1)
               .setIsRunOnce(true)
               .setForEval(true)
               .setNoScriptRval(false)
               .setMutedErrors(mutedErrors)
               .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset)
               .maybeMakeStrictMode(IsStrictEvalPC(pc));

        AutoStableStringChars linearChars(cx);
        if (!linearChars.initTwoByte(cx, linearStr))
            return false;

        const char16_t* chars = linearChars.twoByteRange().start().get();
        SourceBufferHolder::Ownership ownership = linearChars.maybeGiveOwnershipToCaller()
                                                  ? SourceBufferHolder::GiveOwnership
                                                  : SourceBufferHolder::NoOwnership;
        SourceBufferHolder srcBuf(chars, linearStr->length(), ownership);
        JSScript* compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
                                                     scopeobj, staticScope, callerScript,
                                                     options, srcBuf, linearStr, staticLevel);
        if (!compiled)
            return false;

        if (compiled->strict())
            staticScope->setStrict();

        esg.setNewScript(compiled);
    }

    // Primitive 'this' values should have been filtered out by Ion. If boxed,
    // the calling frame cannot be updated to store the new object.
    MOZ_ASSERT(thisValue.isObject() || thisValue.isUndefined() || thisValue.isNull());

    // When eval'ing strict code in a non-strict context, compute the 'this'
    // value to use from what the caller passed in. This isn't necessary if
    // the callee is not strict, as it will compute the non-strict 'this'
    // value as necessary while it executes.
    RootedValue nthisValue(cx, thisValue);
    if (!callerScript->strict() && esg.script()->strict() && !thisValue.isObject()) {
        JSObject* obj = BoxNonStrictThis(cx, thisValue);
        if (!obj)
            return false;
        nthisValue = ObjectValue(*obj);
    }

    return ExecuteKernel(cx, esg.script(), *scopeobj, nthisValue, newTargetValue,
                         ExecuteType(DIRECT_EVAL), NullFramePtr() /* evalInFrame */, vp.address());
}