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); }
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; }
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; }
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; }
js::ToBooleanSlow(HandleValue v) { if (v.isString()) return v.toString()->length() != 0; JS_ASSERT(v.isObject()); return !EmulatesUndefined(&v.toObject()); }
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); }
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); }
// 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()); }