static bool IsVectorObject(HandleValue v) { if (!v.isObject()) return false; JSObject &obj = v.toObject(); if (!obj.is<TypedObject>()) return false; TypeDescr &typeRepr = obj.as<TypedObject>().typeDescr(); if (typeRepr.kind() != TypeDescr::X4) return false; return typeRepr.as<X4TypeDescr>().type() == V::type; }
bool JS::detail::CallMethodIfWrapped(JSContext* cx, IsAcceptableThis test, NativeImpl impl, const CallArgs& args) { HandleValue thisv = args.thisv(); MOZ_ASSERT(!test(thisv)); if (thisv.isObject()) { JSObject& thisObj = args.thisv().toObject(); if (thisObj.is<ProxyObject>()) return Proxy::nativeCall(cx, test, impl, args); } ReportIncompatible(cx, args); return false; }
static Elem TypedObjectMemory(HandleValue v) { TypedObject &obj = v.toObject().as<TypedObject>(); MOZ_ASSERT(!obj.owner().isNeutered()); return reinterpret_cast<Elem>(obj.typedMem()); }
static bool CheckVectorObject(HandleValue v, X4TypeDescr::Type expectedType) { if (!v.isObject()) return false; JSObject &obj = v.toObject(); if (!obj.is<TypedObject>()) return false; TypeDescr &typeRepr = obj.as<TypedObject>().typeDescr(); if (typeRepr.kind() != type::X4) return false; return typeRepr.as<X4TypeDescr>().type() == expectedType; }
/* * ES6 21.2.3.2.2. Because this function only ever returns |obj| in the spec, * provided by the user, we omit it and just return the usual success/failure. */ static bool RegExpInitialize(JSContext* cx, Handle<RegExpObject*> obj, HandleValue patternValue, HandleValue flagsValue, RegExpStaticsUse staticsUse) { RootedAtom pattern(cx); if (patternValue.isUndefined()) { /* Step 1. */ pattern = cx->runtime()->emptyString; } else { /* Steps 2-3. */ pattern = ToAtom<CanGC>(cx, patternValue); if (!pattern) return false; } /* Step 4. */ RegExpFlag flags = RegExpFlag(0); if (!flagsValue.isUndefined()) { /* Steps 5-6. */ RootedString flagStr(cx, ToString<CanGC>(cx, flagsValue)); if (!flagStr) return false; /* Step 7. */ if (!ParseRegExpFlags(cx, flagStr, &flags)) return false; } /* Steps 9-10. */ CompileOptions options(cx); frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr); if (!irregexp::ParsePatternSyntax(dummyTokenStream, cx->tempLifoAlloc(), pattern)) return false; if (staticsUse == UseRegExpStatics) { RegExpStatics* res = cx->global()->getRegExpStatics(cx); if (!res) return false; flags = RegExpFlag(flags | res->getFlags()); } /* Steps 11-15. */ if (!RegExpObject::initFromAtom(cx, obj, pattern, flags)) return false; /* Step 16. */ return true; }
NS_IMETHODIMP nsJSIID::HasInstance(nsIXPConnectWrappedNative* wrapper, JSContext* cx, JSObject * /* unused */, HandleValue val, bool* bp, bool* _retval) { *bp = false; if (val.isPrimitive()) return NS_OK; // we have a JSObject RootedObject obj(cx, &val.toObject()); const nsIID* iid; mInfo->GetIIDShared(&iid); return xpc::HasInstance(cx, obj, iid, bp); }
MOZ_ALWAYS_INLINE bool bool_toSource_impl(JSContext *cx, CallArgs args) { HandleValue thisv = args.thisv(); JS_ASSERT(IsBoolean(thisv)); bool b = thisv.isBoolean() ? thisv.toBoolean() : thisv.toObject().as<BooleanObject>().unbox(); StringBuffer sb(cx); if (!sb.append("(new Boolean(") || !BooleanToStringBuffer(b, sb) || !sb.append("))")) return false; JSString *str = sb.finishString(); if (!str) return false; args.rval().setString(str); return true; }
bool AccessCheck::checkPassToPrivilegedCode(JSContext* cx, HandleObject wrapper, HandleValue v) { // Primitives are fine. if (!v.isObject()) return true; RootedObject obj(cx, &v.toObject()); // Non-wrappers are fine. if (!js::IsWrapper(obj)) return true; // CPOWs use COWs (in the unprivileged junk scope) for all child->parent // references. Without this test, the child process wouldn't be able to // pass any objects at all to CPOWs. if (mozilla::jsipc::IsWrappedCPOW(obj) && js::GetObjectCompartment(wrapper) == js::GetObjectCompartment(xpc::UnprivilegedJunkScope()) && XRE_IsParentProcess()) { return true; } // COWs are fine to pass to chrome if and only if they have __exposedProps__, // since presumably content should never have a reason to pass an opaque // object back to chrome. if (AccessCheck::isChrome(js::UncheckedUnwrap(wrapper)) && WrapperFactory::IsCOW(obj)) { RootedObject target(cx, js::UncheckedUnwrap(obj)); JSAutoCompartment ac(cx, target); RootedId id(cx, GetRTIdByIndex(cx, XPCJSRuntime::IDX_EXPOSEDPROPS)); bool found = false; if (!JS_HasPropertyById(cx, target, id, &found)) return false; if (found) return true; } // Same-origin wrappers are fine. if (AccessCheck::wrapperSubsumes(obj)) return true; // Badness. JS_ReportError(cx, "Permission denied to pass object to privileged code"); return false; }
static bool ProtoGetterImpl(JSContext *cx, CallArgs args) { JS_ASSERT(TestProtoGetterThis(args.thisv())); HandleValue thisv = args.thisv(); if (thisv.isPrimitive() && !BoxNonStrictThis(cx, args)) return false; unsigned dummy; RootedObject obj(cx, &args.thisv().toObject()); RootedId nid(cx, NameToId(cx->names().proto)); RootedValue v(cx); if (!CheckAccess(cx, obj, nid, JSACC_PROTO, &v, &dummy)) return false; args.rval().set(v); return true; }
static bool ProtoGetter(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); HandleValue thisv = args.thisv(); if (thisv.isNullOrUndefined()) { ReportIncompatible(cx, args); return false; } if (thisv.isPrimitive() && !BoxNonStrictThis(cx, args)) return false; RootedObject obj(cx, &args.thisv().toObject()); RootedObject proto(cx); if (!GetPrototype(cx, obj, &proto)) return false; args.rval().setObjectOrNull(proto); return true; }
bool CreateObjectIn(JSContext *cx, HandleValue vobj, CreateObjectInOptions &options, MutableHandleValue rval) { if (!vobj.isObject()) { JS_ReportError(cx, "Expected an object as the target scope"); return false; } RootedObject scope(cx, js::CheckedUnwrap(&vobj.toObject())); if (!scope) { JS_ReportError(cx, "Permission denied to create object in the target scope"); return false; } bool define = !JSID_IS_VOID(options.defineAs); if (define && js::IsScriptedProxy(scope)) { JS_ReportError(cx, "Defining property on proxy object is not allowed"); return false; } RootedObject obj(cx); { JSAutoCompartment ac(cx, scope); obj = JS_NewObject(cx, nullptr, JS::NullPtr(), scope); if (!obj) return false; if (define) { if (!JS_DefinePropertyById(cx, scope, options.defineAs, obj, JSPROP_ENUMERATE, JS_PropertyStub, JS_StrictPropertyStub)) return false; } } rval.setObject(*obj); if (!WrapperFactory::WaiveXrayAndWrap(cx, rval)) return false; return true; }
bool WrapperOwner::DOMQI(JSContext* cx, JS::HandleObject proxy, JS::CallArgs& args) { // Someone's calling us, handle nsISupports specially to avoid unnecessary // CPOW traffic. HandleValue id = args[0]; if (id.isObject()) { RootedObject idobj(cx, &id.toObject()); nsCOMPtr<nsIJSID> jsid; nsresult rv = UnwrapArg<nsIJSID>(cx, idobj, getter_AddRefs(jsid)); if (NS_SUCCEEDED(rv)) { MOZ_ASSERT(jsid, "bad wrapJS"); const nsID* idptr = jsid->GetID(); if (idptr->Equals(NS_GET_IID(nsISupports))) { args.rval().set(args.thisv()); return true; } // Webidl-implemented DOM objects never have nsIClassInfo. if (idptr->Equals(NS_GET_IID(nsIClassInfo))) return Throw(cx, NS_ERROR_NO_INTERFACE); } } // It wasn't nsISupports, call into the other process to do the QI for us // (since we don't know what other interfaces our object supports). Note // that we have to use JS_GetPropertyDescriptor here to avoid infinite // recursion back into CPOWDOMQI via WrapperOwner::get(). // We could stash the actual QI function on our own function object to avoid // if we're called multiple times, but since we're transient, there's no // point right now. JS::Rooted<PropertyDescriptor> propDesc(cx); if (!JS_GetPropertyDescriptor(cx, proxy, "QueryInterface", &propDesc)) return false; if (!propDesc.value().isObject()) { MOZ_ASSERT_UNREACHABLE("We didn't get QueryInterface off a node"); return Throw(cx, NS_ERROR_UNEXPECTED); } return JS_CallFunctionValue(cx, proxy, propDesc.value(), args, args.rval()); }
static bool ProtoSetter(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Do this here, rather than after the this-check so even likely-buggy // use of the __proto__ setter on unacceptable values, where no subsequent // use occurs on an acceptable value, will trigger a warning. RootedObject callee(cx, &args.callee()); if (!GlobalObject::warnOnceAboutPrototypeMutation(cx, callee)) return false; HandleValue thisv = args.thisv(); if (thisv.isNullOrUndefined()) { ReportIncompatible(cx, args); return false; } if (thisv.isPrimitive()) { // Mutating a boxed primitive's [[Prototype]] has no side effects. args.rval().setUndefined(); return true; } if (!cx->runningWithTrustedPrincipals()) ++sSetProtoCalled; Rooted<JSObject*> obj(cx, &args.thisv().toObject()); /* Do nothing if __proto__ isn't being set to an object or null. */ if (args.length() == 0 || !args[0].isObjectOrNull()) { args.rval().setUndefined(); return true; } Rooted<JSObject*> newProto(cx, args[0].toObjectOrNull()); if (!SetPrototype(cx, obj, newProto)) return false; args.rval().setUndefined(); return true; }
bool js::ToSimdConstant(JSContext* cx, HandleValue v, jit::SimdConstant* out) { typedef typename V::Elem Elem; Rooted<TypeDescr*> typeDescr(cx, &V::GetTypeDescr(*cx->global())); if (!IsVectorObject<V>(v)) return ErrorWrongTypeArg(cx, 1, typeDescr); Elem* mem = reinterpret_cast<Elem*>(v.toObject().as<TypedObject>().typedMem()); *out = jit::SimdConstant::CreateX4(mem); return true; }
static bool GetDataProperty(JSContext *cx, HandleValue objVal, HandlePropertyName field, MutableHandleValue v) { if (!objVal.isObject()) return LinkFail(cx, "accessing property of non-object"); Rooted<JSPropertyDescriptor> desc(cx); RootedObject obj(cx, &objVal.toObject()); RootedId id(cx, NameToId(field)); if (!JS_GetPropertyDescriptorById(cx, obj, id, 0, &desc)) return false; if (!desc.object()) return LinkFail(cx, "property not present on object"); if (desc.hasGetterOrSetterObject()) return LinkFail(cx, "property is not a data property"); v.set(desc.value()); return true; }
// ES6 rev 25 (2014 May 22) 19.4.2.7 bool SymbolObject::keyFor(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); // step 1 HandleValue arg = args.get(0); if (!arg.isSymbol()) { js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE, JSDVG_SEARCH_STACK, arg, js::NullPtr(), "not a symbol", nullptr); return false; } // step 2 if (arg.toSymbol()->code() == JS::SymbolCode::InSymbolRegistry) { #ifdef DEBUG RootedString desc(cx, arg.toSymbol()->description()); MOZ_ASSERT(Symbol::for_(cx, desc) == arg.toSymbol()); #endif args.rval().setString(arg.toSymbol()->description()); return true; } // step 3: omitted // step 4 args.rval().setUndefined(); return true; }
MOZ_ALWAYS_INLINE bool Proxy::setInternal(JSContext* cx, HandleObject proxy, HandleId id, HandleValue v, HandleValue receiver, ObjectOpResult& result) { MOZ_ASSERT_IF(receiver.isObject(), !IsWindow(&receiver.toObject())); if (!CheckRecursionLimit(cx)) return false; const BaseProxyHandler* handler = proxy->as<ProxyObject>().handler(); AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::SET, true); if (!policy.allowed()) { if (!policy.returnValue()) return false; return result.succeed(); } // Special case. See the comment on BaseProxyHandler::mHasPrototype. if (handler->hasPrototype()) return handler->BaseProxyHandler::set(cx, proxy, id, v, receiver, result); return handler->set(cx, proxy, id, v, receiver, result); }
bool xpc_qsJsvalToCharStr(JSContext *cx, HandleValue v, JSAutoByteString *bytes) { MOZ_ASSERT(!bytes->ptr()); if (v.isNullOrUndefined()) return true; JSString *str = ToString(cx, v); if (!str) return false; return !!bytes->encodeLatin1(cx, str); }
bool js::GeneratorThrowOrClose(JSContext* cx, AbstractFramePtr frame, Handle<GeneratorObject*> genObj, HandleValue arg, uint32_t resumeKind) { if (resumeKind == GeneratorObject::THROW) { cx->setPendingException(arg); genObj->setRunning(); } else { MOZ_ASSERT(resumeKind == GeneratorObject::CLOSE); if (genObj->is<StarGeneratorObject>()) { MOZ_ASSERT(arg.isObject()); frame.setReturnValue(arg); } else { MOZ_ASSERT(arg.isUndefined()); } cx->setPendingException(MagicValue(JS_GENERATOR_CLOSING)); genObj->setClosing(); } return false; }
static bool ProtoSetterImpl(JSContext *cx, CallArgs args) { JS_ASSERT(TestProtoThis(args.thisv())); HandleValue thisv = args.thisv(); if (thisv.isPrimitive()) { JS_ASSERT(!thisv.isNullOrUndefined()); // Mutating a boxed primitive's [[Prototype]] has no side effects. args.rval().setUndefined(); return true; } if (!cx->runningWithTrustedPrincipals()) ++sSetProtoCalled; Rooted<JSObject*> obj(cx, &args.thisv().toObject()); /* Do nothing if __proto__ isn't being set to an object or null. */ if (args.length() == 0 || !args[0].isObjectOrNull()) { args.rval().setUndefined(); return true; } Rooted<JSObject*> newProto(cx, args[0].toObjectOrNull()); bool success; if (!JSObject::setProto(cx, obj, newProto, &success)) return false; if (!success) { js_ReportValueError(cx, JSMSG_SETPROTOTYPEOF_FAIL, JSDVG_IGNORE_STACK, thisv, js::NullPtr()); return false; } args.rval().setUndefined(); return true; }
bool js::ToSimdConstant(JSContext *cx, HandleValue v, jit::SimdConstant *out) { typedef typename V::Elem Elem; if (!IsVectorObject<V>(v)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SIMD_NOT_A_VECTOR); return false; } Elem *mem = reinterpret_cast<Elem *>(v.toObject().as<TypedObject>().typedMem()); *out = jit::SimdConstant::CreateX4(mem); return true; }
static bool HasPureCoercion(JSContext *cx, HandleValue v) { if (IsVectorObject<Int32x4>(v) || IsVectorObject<Float32x4>(v)) return true; // Ideally, we'd reject all non-SIMD non-primitives, but Emscripten has a // bug that generates code that passes functions for some imports. To avoid // breaking all the code that contains this bug, we make an exception for // functions that don't have user-defined valueOf or toString, for their // coercions are not observable and coercion via ToNumber/ToInt32 // definitely produces NaN/0. We should remove this special case later once // most apps have been built with newer Emscripten. jsid toString = NameToId(cx->names().toString); if (v.toObject().is<JSFunction>() && HasObjectValueOf(&v.toObject(), cx) && ClassMethodIsNative(cx, &v.toObject().as<JSFunction>(), &JSFunction::class_, toString, fun_toString)) { return true; } return false; }
static MOZ_ALWAYS_INLINE bool SetWeakMapEntryInternal(JSContext* cx, Handle<WeakMapObject*> mapObj, HandleObject key, HandleValue value) { ObjectValueMap* map = mapObj->getMap(); if (!map) { AutoInitGCManagedObject<ObjectValueMap> newMap( cx->make_unique<ObjectValueMap>(cx, mapObj.get())); if (!newMap) return false; if (!newMap->init()) { JS_ReportOutOfMemory(cx); return false; } map = newMap.release(); mapObj->setPrivate(map); } // Preserve wrapped native keys to prevent wrapper optimization. if (!TryPreserveReflector(cx, key)) return false; if (JSWeakmapKeyDelegateOp op = key->getClass()->ext.weakmapKeyDelegateOp) { RootedObject delegate(cx, op(key)); if (delegate && !TryPreserveReflector(cx, delegate)) return false; } MOZ_ASSERT(key->compartment() == mapObj->compartment()); MOZ_ASSERT_IF(value.isObject(), value.toObject().compartment() == mapObj->compartment()); if (!map->put(key, value)) { JS_ReportOutOfMemory(cx); return false; } WeakMapPostWriteBarrier(cx->runtime(), map, key.get()); return true; }
static bool ReadCustomFloat32NaNObject(JSContext* cx, HandleValue v, float* ret) { RootedObject obj(cx, &v.toObject()); RootedValue val(cx); int32_t i32; if (!JS_GetProperty(cx, obj, "nan_low", &val)) return false; if (!ToInt32(cx, val, &i32)) return false; BitwiseCast(i32, ret); return true; }
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::IsSharedArrayBuffer(HandleValue v) { return v.isObject() && v.toObject().is<SharedArrayBufferObject>(); }
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()); }
/* static */ bool ModuleObject::isInstance(HandleValue value) { return value.isObject() && value.toObject().is<ModuleObject>(); }
MOZ_ALWAYS_INLINE bool IsBoolean(HandleValue v) { return v.isBoolean() || (v.isObject() && v.toObject().is<BooleanObject>()); }
/* static */ bool ImportEntryObject::isInstance(HandleValue value) { return value.isObject() && value.toObject().is<ImportEntryObject>(); }