示例#1
0
文件: Eval.cpp 项目: martasect/gecko
bool
js::DirectEvalStringFromIon(JSContext *cx,
                            HandleObject scopeobj, HandleScript callerScript,
                            HandleValue thisValue, HandleString str,
                            jsbytecode *pc, MutableHandleValue vp)
{
    AssertInnerizedScopeChain(cx, *scopeobj);

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

    // ES5 15.1.2.1 steps 2-8.

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

    Rooted<JSFlatString*> flatStr(cx, str->ensureFlat(cx));
    if (!flatStr)
        return false;

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

    EvalScriptGuard esg(cx);

    esg.lookupInEvalCache(flatStr, callerScript, pc);

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

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

        CompileOptions options(cx);
        options.setFileAndLine(filename, 1)
               .setCompileAndGo(true)
               .setForEval(true)
               .setNoScriptRval(false)
               .setOriginPrincipals(originPrincipals)
               .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);

        AutoStableStringChars flatChars(cx);
        if (!flatChars.initTwoByte(cx, flatStr))
            return false;

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

        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.
    JS_ASSERT(thisValue.isObject() || thisValue.isUndefined() || thisValue.isNull());

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

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

    // ES5 15.1.2.1 steps 2-8.

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

    Rooted<JSFlatString*> flatStr(cx, str->ensureFlat(cx));
    if (!flatStr)
        return false;

    size_t length = flatStr->length();
    ConstTwoByteChars chars(flatStr->chars(), length);

    EvalJSONResult ejr = TryEvalJSON(cx, callerScript, chars, length, vp);
    if (ejr != EvalJSON_NotJSON)
        return ejr == EvalJSON_Success;

    EvalScriptGuard esg(cx);

    // Ion will not perform cross compartment direct eval calls.
    JSPrincipals *principals = cx->compartment()->principals;

    esg.lookupInEvalCache(flatStr, callerScript, pc);

    if (!esg.foundScript()) {
        JSScript *script;
        const char *filename;
        unsigned lineno;
        JSPrincipals *originPrincipals;
        uint32_t pcOffset;
        CurrentScriptFileLineOrigin(cx, &script, &filename, &lineno, &pcOffset,
                                    &originPrincipals, CALLED_FROM_JSOP_EVAL);

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

        CompileOptions options(cx);
        options.setFileAndLine(filename, 1)
               .setCompileAndGo(true)
               .setForEval(true)
               .setNoScriptRval(false)
               .setPrincipals(principals)
               .setOriginPrincipals(originPrincipals)
               .setIntroductionInfo(introducerFilename, "eval", lineno, script, pcOffset);
        JSScript *compiled = frontend::CompileScript(cx, &cx->tempLifoAlloc(),
                                                     scopeobj, callerScript, options,
                                                     chars.get(), length, flatStr, staticLevel);
        if (!compiled)
            return false;

        MarkFunctionsWithinEvalScript(compiled);

        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.
    JS_ASSERT(thisValue.isObject() || thisValue.isUndefined() || thisValue.isNull());

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