Ejemplo n.º 1
0
static bool
CloneValue(JSContext *cx, HandleValue selfHostedValue, MutableHandleValue vp)
{
    if (selfHostedValue.isObject()) {
        RootedObject selfHostedObject(cx, &selfHostedValue.toObject());
        JSObject *clone = CloneObject(cx, selfHostedObject);
        if (!clone)
            return false;
        vp.setObject(*clone);
    } else if (selfHostedValue.isBoolean() || selfHostedValue.isNumber() || selfHostedValue.isNullOrUndefined()) {
        // Nothing to do here: these are represented inline in the value.
        vp.set(selfHostedValue);
    } else if (selfHostedValue.isString()) {
        if (!selfHostedValue.toString()->isFlat())
            MOZ_CRASH();
        JSFlatString *selfHostedString = &selfHostedValue.toString()->asFlat();
        JSString *clone = CloneString(cx, selfHostedString);
        if (!clone)
            return false;
        vp.setString(clone);
    } else {
        MOZ_CRASH("Self-hosting CloneValue can't clone given value.");
    }
    return true;
}
Ejemplo n.º 2
0
static bool
CloneValue(JSContext *cx, HandleValue selfHostedValue, MutableHandleValue vp)
{
    if (selfHostedValue.isObject()) {
        RootedNativeObject selfHostedObject(cx, &selfHostedValue.toObject().as<NativeObject>());
        JSObject *clone = CloneObject(cx, selfHostedObject);
        if (!clone)
            return false;
        vp.setObject(*clone);
    } else if (selfHostedValue.isBoolean() || selfHostedValue.isNumber() || selfHostedValue.isNullOrUndefined()) {
        // Nothing to do here: these are represented inline in the value.
        vp.set(selfHostedValue);
    } else if (selfHostedValue.isString()) {
        if (!selfHostedValue.toString()->isFlat())
            MOZ_CRASH();
        JSFlatString *selfHostedString = &selfHostedValue.toString()->asFlat();
        JSString *clone = CloneString(cx, selfHostedString);
        if (!clone)
            return false;
        vp.setString(clone);
    } else if (selfHostedValue.isSymbol()) {
        // Well-known symbols are shared.
        mozilla::DebugOnly<JS::Symbol *> sym = selfHostedValue.toSymbol();
        MOZ_ASSERT(sym->isWellKnownSymbol());
        MOZ_ASSERT(cx->wellKnownSymbols().get(size_t(sym->code())) == sym);
        vp.set(selfHostedValue);
    } else {
        MOZ_CRASH("Self-hosting CloneValue can't clone given value.");
    }
    return true;
}
Ejemplo n.º 3
0
static bool
CompareMaybeStringsPar(ForkJoinContext *cx, HandleValue v1, HandleValue v2, int32_t *res)
{
    if (!v1.isString())
        return false;
    if (!v2.isString())
        return false;
    return CompareStringsPar(cx, v1.toString(), v2.toString(), res);
}
static ParallelResult
CompareMaybeStringsPar(ForkJoinSlice *slice, HandleValue v1, HandleValue v2, int32_t *res)
{
    if (!v1.isString())
        return TP_RETRY_SEQUENTIALLY;
    if (!v2.isString())
        return TP_RETRY_SEQUENTIALLY;
    return CompareStringsPar(slice, v1.toString(), v2.toString(), res);
}
Ejemplo n.º 5
0
bool
HashableValue::setValue(JSContext* cx, HandleValue v)
{
    if (v.isString()) {
        // Atomize so that hash() and operator==() are fast and infallible.
        JSString* str = AtomizeString(cx, v.toString(), DoNotPinAtom);
        if (!str)
            return false;
        value = StringValue(str);
    } else if (v.isDouble()) {
        double d = v.toDouble();
        int32_t i;
        if (NumberEqualsInt32(d, &i)) {
            // Normalize int32_t-valued doubles to int32_t for faster hashing and testing.
            value = Int32Value(i);
        } else if (IsNaN(d)) {
            // NaNs with different bits must hash and test identically.
            value = DoubleNaNValue();
        } else {
            value = v;
        }
    } else {
        value = v;
    }

    MOZ_ASSERT(value.isUndefined() || value.isNull() || value.isBoolean() || value.isNumber() ||
               value.isString() || value.isSymbol() || value.isObject());
    return true;
}
Ejemplo n.º 6
0
js::ToBooleanSlow(HandleValue v)
{
    if (v.isString())
        return v.toString()->length() != 0;

    JS_ASSERT(v.isObject());
    return !EmulatesUndefined(&v.toObject());
}
Ejemplo n.º 7
0
Node::Node(HandleValue value)
{
    if (value.isObject())
        construct(&value.toObject());
    else if (value.isString())
        construct(value.toString());
    else if (value.isSymbol())
        construct(value.toSymbol());
    else
        construct<void>(nullptr);
}
Ejemplo n.º 8
0
bool
js::DirectEvalValueFromIon(JSContext *cx,
                           HandleObject scopeobj, HandleScript callerScript,
                           HandleValue thisValue, HandleValue evalArg,
                           jsbytecode *pc, MutableHandleValue vp)
{
    // Act as identity on non-strings per ES5 15.1.2.1 step 1.
    if (!evalArg.isString()) {
        vp.set(evalArg);
        return true;
    }

    RootedString string(cx, evalArg.toString());
    return DirectEvalStringFromIon(cx, scopeobj, callerScript, thisValue, string, pc, vp);
}
Ejemplo n.º 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, HandleValue v, EvalType evalType, AbstractFramePtr caller,
           HandleObject scopeobj, jsbytecode* pc, MutableHandleValue vp)
{
    MOZ_ASSERT((evalType == INDIRECT_EVAL) == !caller);
    MOZ_ASSERT((evalType == INDIRECT_EVAL) == !pc);
    MOZ_ASSERT_IF(evalType == INDIRECT_EVAL, IsGlobalLexicalScope(scopeobj));
    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 step 1.
    if (!v.isString()) {
        vp.set(v);
        return true;
    }
    RootedString str(cx, v.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'.)
    MOZ_ASSERT_IF(evalType != DIRECT_EVAL,
                  cx->global() == &scopeobj->as<ClonedBlockObject>().global());

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

    RootedScript callerScript(cx, caller ? caller.script() : nullptr);
    EvalJSONResult ejr = TryEvalJSON(cx, linearStr, vp);
    if (ejr != EvalJSON_NotJSON)
        return ejr == EvalJSON_Success;

    EvalScriptGuard esg(cx);

    if (evalType == DIRECT_EVAL && caller.isFunctionFrame())
        esg.lookupInEvalCache(linearStr, callerScript, pc);

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

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

        RootedObject enclosing(cx);
        if (evalType == DIRECT_EVAL)
            enclosing = callerScript->innermostStaticScope(pc);
        else
            enclosing = &cx->global()->lexicalScope().staticBlock();
        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(evalType == DIRECT_EVAL && 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);
    }

    // Look up the newTarget from the frame iterator.
    Value newTargetVal = NullValue();
    return ExecuteKernel(cx, esg.script(), *scopeobj, newTargetVal,
                         NullFramePtr() /* evalInFrame */, vp.address());
}