bool BaseDOMProxyHandler::getPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, MutableHandle<JSPropertyDescriptor> desc, unsigned flags) { if (!getOwnPropertyDescriptor(cx, proxy, id, desc, flags)) { return false; } if (desc.object()) { return true; } JS::Rooted<JSObject*> proto(cx); if (!js::GetObjectProto(cx, proxy, &proto)) { return false; } if (!proto) { desc.object().set(nullptr); return true; } return JS_GetPropertyDescriptorById(cx, proto, id, 0, desc); }
bool SavedStacks::insertFrames(JSContext *cx, ScriptFrameIter &iter, MutableHandle<SavedFrame*> frame) { if (iter.done()) { frame.set(nullptr); return true; } ScriptFrameIter thisFrame(iter); Rooted<SavedFrame*> parentFrame(cx); if (!insertFrames(cx, ++iter, &parentFrame)) return false; RootedScript script(cx, thisFrame.script()); RootedFunction callee(cx, thisFrame.maybeCallee()); const char *filename = script->filename(); RootedAtom source(cx, Atomize(cx, filename, strlen(filename))); if (!source) return false; uint32_t column; uint32_t line = PCToLineNumber(script, thisFrame.pc(), &column); SavedFrame::Lookup lookup(source, line, column, callee ? callee->displayAtom() : nullptr, parentFrame, thisFrame.compartment()->principals); frame.set(getOrCreateSavedFrame(cx, lookup)); return frame.address() != nullptr; }
bool JSCompartment::wrap(JSContext *cx, MutableHandle<PropDesc> desc) { if (desc.isUndefined()) return true; JSCompartment *comp = cx->compartment(); if (desc.hasValue()) { RootedValue value(cx, desc.value()); if (!comp->wrap(cx, &value)) return false; desc.setValue(value); } if (desc.hasGet()) { RootedValue get(cx, desc.getterValue()); if (!comp->wrap(cx, &get)) return false; desc.setGetter(get); } if (desc.hasSet()) { RootedValue set(cx, desc.setterValue()); if (!comp->wrap(cx, &set)) return false; desc.setSetter(set); } return true; }
bool InterposeProperty(JSContext* cx, HandleObject target, const nsIID* iid, HandleId id, MutableHandle<JSPropertyDescriptor> descriptor) { // We only want to do interpostion on DOM instances and // wrapped natives. RootedObject unwrapped(cx, UncheckedUnwrap(target)); const js::Class* clasp = js::GetObjectClass(unwrapped); if (!mozilla::dom::IsDOMClass(clasp) && !IS_WN_CLASS(clasp) && !IS_PROTO_CLASS(clasp) && clasp != &OuterWindowProxyClass) { return true; } XPCWrappedNativeScope* scope = ObjectScope(CurrentGlobalOrNull(cx)); MOZ_ASSERT(scope->HasInterposition()); nsCOMPtr<nsIAddonInterposition> interp = scope->GetInterposition(); JSAddonId* addonId = AddonIdOfObject(target); RootedValue addonIdValue(cx, StringValue(StringOfAddonId(addonId))); RootedValue prop(cx, IdToValue(id)); RootedValue targetValue(cx, ObjectValue(*target)); RootedValue descriptorVal(cx); nsresult rv = interp->InterposeProperty(addonIdValue, targetValue, iid, prop, &descriptorVal); if (NS_FAILED(rv)) { xpc::Throw(cx, rv); return false; } if (!descriptorVal.isObject()) return true; // We need to be careful parsing descriptorVal. |cx| is in the compartment // of the add-on and the descriptor is in the compartment of the // interposition. We could wrap the descriptor in the add-on's compartment // and then parse it. However, parsing the descriptor fetches properties // from it, and we would try to interpose on those property accesses. So // instead we parse in the interposition's compartment and then wrap the // descriptor. { JSAutoCompartment ac(cx, &descriptorVal.toObject()); if (!JS::ObjectToCompletePropertyDescriptor(cx, target, descriptorVal, descriptor)) return false; } // Always make the property non-configurable regardless of what the // interposition wants. descriptor.setAttributes(descriptor.attributes() | JSPROP_PERMANENT); if (!JS_WrapPropertyDescriptor(cx, descriptor)) return false; return true; }
bool JavaScriptShared::toDescriptor(JSContext* cx, const PPropertyDescriptor& in, MutableHandle<JSPropertyDescriptor> out) { out.setAttributes(in.attrs()); if (!fromVariant(cx, in.value(), out.value())) return false; out.object().set(fromObjectOrNullVariant(cx, in.obj())); if (in.getter().type() == GetterSetter::Tuint64_t && !in.getter().get_uint64_t()) { out.setGetter(nullptr); } else if (in.attrs() & JSPROP_GETTER) { Rooted<JSObject*> getter(cx); getter = fromObjectVariant(cx, in.getter().get_ObjectVariant()); if (!getter) return false; out.setGetter(JS_DATA_TO_FUNC_PTR(JSGetterOp, getter.get())); } else { out.setGetter(UnknownPropertyStub); } if (in.setter().type() == GetterSetter::Tuint64_t && !in.setter().get_uint64_t()) { out.setSetter(nullptr); } else if (in.attrs() & JSPROP_SETTER) { Rooted<JSObject*> setter(cx); setter = fromObjectVariant(cx, in.setter().get_ObjectVariant()); if (!setter) return false; out.setSetter(JS_DATA_TO_FUNC_PTR(JSSetterOp, setter.get())); } else { out.setSetter(UnknownStrictPropertyStub); } return true; }
static bool GetSharedTypedArray(JSContext* cx, HandleValue v, MutableHandle<TypedArrayObject*> viewp) { if (!v.isObject()) return ReportBadArrayType(cx); if (!v.toObject().is<TypedArrayObject>()) return ReportBadArrayType(cx); viewp.set(&v.toObject().as<TypedArrayObject>()); if (!viewp->isSharedMemory()) return ReportBadArrayType(cx); return true; }
bool SecurityWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id, MutableHandle<PropertyDescriptor> desc) { if (desc.getter() || desc.setter()) { JSString *str = IdToString(cx, id); const jschar *prop = str ? str->getCharsZ(cx) : nullptr; JS_ReportErrorNumberUC(cx, js_GetErrorMessage, nullptr, JSMSG_ACCESSOR_DEF_DENIED, prop); return false; } return Base::defineProperty(cx, wrapper, id, desc); }
static bool CloneModule(JSContext* cx, MutableHandle<AsmJSModuleObject*> moduleObj) { ScopedJSDeletePtr<AsmJSModule> module; if (!moduleObj->module().clone(cx, &module)) return false; AsmJSModuleObject* newModuleObj = AsmJSModuleObject::create(cx, &module); if (!newModuleObj) return false; moduleObj.set(newModuleObj); return true; }
bool BaselineFrame::copyRawFrameSlots(MutableHandle<GCVector<Value>> vec) const { unsigned nfixed = script()->nfixed(); unsigned nformals = numFormalArgs(); if (!vec.resize(nformals + nfixed)) return false; mozilla::PodCopy(vec.begin(), argv(), nformals); for (unsigned i = 0; i < nfixed; i++) vec[nformals + i].set(*valueSlot(i)); return true; }
bool WaiveXrayWrapper::getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id, MutableHandle<PropertyDescriptor> desc) const { return CrossCompartmentWrapper::getOwnPropertyDescriptor(cx, wrapper, id, desc) && WrapperFactory::WaiveXrayAndWrap(cx, desc.value()) && WaiveAccessors(cx, desc); }
static bool FillVector(JSContext* cx, MutableHandle<ShapeVec> shapes) { for (size_t i = 0; i < 10; ++i) { RootedObject obj(cx, JS_NewObject(cx, nullptr)); RootedValue val(cx, UndefinedValue()); // Construct a unique property name to ensure that the object creates a // new shape. char buffer[2]; buffer[0] = 'a' + i; buffer[1] = '\0'; if (!JS_SetProperty(cx, obj, buffer, val)) return false; if (!shapes.append(obj->as<NativeObject>().lastProperty())) return false; } // Ensure iterator enumeration works through the mutable handle. for (auto shape : shapes) { if (!shape) return false; } return true; }
static bool ImportFunctions(JSContext* cx, HandleObject importObj, const ImportNameVector& importNames, MutableHandle<FunctionVector> imports) { if (!importNames.empty() && !importObj) return Fail(cx, "no import object given"); for (const ImportName& name : importNames) { RootedValue v(cx); if (!GetProperty(cx, importObj, name.module.get(), &v)) return false; if (*name.func.get()) { if (!v.isObject()) return Fail(cx, "import object field is not an Object"); RootedObject obj(cx, &v.toObject()); if (!GetProperty(cx, obj, name.func.get(), &v)) return false; } if (!IsFunctionObject(v)) return Fail(cx, "import object field is not a Function"); if (!imports.append(&v.toObject().as<JSFunction>())) return false; } return true; }
bool js::XDRScriptRegExpObject(XDRState<mode>* xdr, MutableHandle<RegExpObject*> objp) { /* NB: Keep this in sync with CloneScriptRegExpObject. */ RootedAtom source(xdr->cx()); uint32_t flagsword = 0; if (mode == XDR_ENCODE) { MOZ_ASSERT(objp); RegExpObject& reobj = *objp; source = reobj.getSource(); flagsword = reobj.getFlags(); } if (!XDRAtom(xdr, &source) || !xdr->codeUint32(&flagsword)) return false; if (mode == XDR_DECODE) { RegExpFlag flags = RegExpFlag(flagsword); RegExpObject* reobj = RegExpObject::createNoStatics(xdr->cx(), source, flags, nullptr, xdr->cx()->tempLifoAlloc()); if (!reobj) return false; objp.set(reobj); } return true; }
bool SecurityWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id, MutableHandle<PropertyDescriptor> desc) const { if (desc.getter() || desc.setter()) { JSString *str = IdToString(cx, id); AutoStableStringChars chars(cx); const jschar *prop = nullptr; if (str->ensureFlat(cx) && chars.initTwoByte(cx, str)) prop = chars.twoByteChars(); JS_ReportErrorNumberUC(cx, js_GetErrorMessage, nullptr, JSMSG_ACCESSOR_DEF_DENIED, prop); return false; } return Base::defineProperty(cx, wrapper, id, desc); }
static bool proxy_LookupProperty(JSContext* cx, HandleObject obj, HandleId id, MutableHandleObject objp, MutableHandle<JS::PropertyResult> propp) { bool found; if (!Proxy::has(cx, obj, id, &found)) return false; if (found) { propp.setNonNativeProperty(); objp.set(obj); } else { propp.setNotFound(); objp.set(nullptr); } return true; }
bool OpaqueCrossCompartmentWrapper::getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id, MutableHandle<PropertyDescriptor> desc) const { desc.object().set(nullptr); return true; }
bool JSCompartment::wrap(JSContext* cx, MutableHandle<GCVector<Value>> vec) { for (size_t i = 0; i < vec.length(); ++i) { if (!wrap(cx, vec[i])) return false; } return true; }
bool impl(JSContext *cx, HandleObject proxy, HandleId id, MutableHandle<JSPropertyDescriptor> desc, bool ownOnly) const { if (JSID_IS_STRING(id)) { bool match; if (!JS_StringEqualsAscii(cx, JSID_TO_STRING(id), "phantom", &match)) return false; if (match) { desc.object().set(proxy); desc.attributesRef() = JSPROP_READONLY | JSPROP_ENUMERATE; desc.value().setInt32(42); return true; } } if (ownOnly) return DirectProxyHandler::getOwnPropertyDescriptor(cx, proxy, id, desc); return DirectProxyHandler::getPropertyDescriptor(cx, proxy, id, desc); }
bool BaseProxyHandler::getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id, MutableHandle<PropertyDescriptor> desc) const { assertEnteredPolicy(cx, proxy, id, GET | SET | GET_PROPERTY_DESCRIPTOR); if (!getOwnPropertyDescriptor(cx, proxy, id, desc)) return false; if (desc.object()) return true; RootedObject proto(cx); if (!GetPrototype(cx, proxy, &proto)) return false; if (!proto) { MOZ_ASSERT(!desc.object()); return true; } return GetPropertyDescriptor(cx, proto, id, desc); }
bool SecurityWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id, MutableHandle<PropertyDescriptor> desc, ObjectOpResult &result) const { if (desc.getter() || desc.setter()) { RootedValue idVal(cx, IdToValue(id)); JSString *str = ValueToSource(cx, idVal); if (!str) return false; AutoStableStringChars chars(cx); const char16_t *prop = nullptr; if (str->ensureFlat(cx) && chars.initTwoByte(cx, str)) prop = chars.twoByteChars(); JS_ReportErrorNumberUC(cx, GetErrorMessage, nullptr, JSMSG_ACCESSOR_DEF_DENIED, prop); return false; } return Base::defineProperty(cx, wrapper, id, desc, result); }
bool AddonWrapper<Base>::getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id, MutableHandle<JSPropertyDescriptor> desc) const { if (!InterposeProperty(cx, wrapper, nullptr, id, desc)) return false; if (desc.object()) return true; return Base::getOwnPropertyDescriptor(cx, wrapper, id, desc); }
bool SavedStacks::insertFrames(JSContext *cx, ScriptFrameIter &iter, MutableHandle<SavedFrame*> frame) { if (iter.done()) { frame.set(nullptr); return true; } // Don't report the over-recursion error because if we are blowing the stack // here, we already blew the stack in JS, reported it, and we are creating // the saved stack for the over-recursion error object. We do this check // here, rather than inside saveCurrentStack, because in some cases we will // pass the check there, despite later failing the check here (for example, // in js/src/jit-test/tests/saved-stacks/bug-1006876-too-much-recursion.js). JS_CHECK_RECURSION_DONT_REPORT(cx, return false); ScriptFrameIter thisFrame(iter); Rooted<SavedFrame*> parentFrame(cx); if (!insertFrames(cx, ++iter, &parentFrame)) return false; RootedScript script(cx, thisFrame.script()); RootedFunction callee(cx, thisFrame.maybeCallee()); const char *filename = script->filename(); RootedAtom source(cx, Atomize(cx, filename, strlen(filename))); if (!source) return false; uint32_t column; uint32_t line = PCToLineNumber(script, thisFrame.pc(), &column); SavedFrame::Lookup lookup(source, line, column, callee ? callee->displayAtom() : nullptr, parentFrame, thisFrame.compartment()->principals); frame.set(getOrCreateSavedFrame(cx, lookup)); return frame.get() != nullptr; }
bool Proxy::getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id, MutableHandle<PropertyDescriptor> desc) { if (!CheckRecursionLimit(cx)) return false; const BaseProxyHandler* handler = proxy->as<ProxyObject>().handler(); desc.object().set(nullptr); // default result if we refuse to perform this action AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET_PROPERTY_DESCRIPTOR, true); if (!policy.allowed()) return policy.returnValue(); return handler->getOwnPropertyDescriptor(cx, proxy, id, desc); }
bool SetRenderTargetProperty( JSContext *cx, Handle<JSObject *> object, Handle<jsid> id, bool, MutableHandle<Value> value) { RootedValue val(cx); JS_IdToValue( cx, id, MutableHandleValue(&val) ); JSString *propertyString = val.toString(); const char *propertyName=JS_EncodeString(cx, propertyString); //printf("SetRenderTargetProperty: %s\n", propertyName ); RenderTarget *target=(RenderTarget *) JS_GetPrivate( object ); if ( !strcmp( propertyName, "w" ) ) { target->w=value.toInt32(); } else if ( !strcmp( propertyName, "h" ) ) { target->h=value.toInt32(); } else if ( !strcmp( propertyName, "autoResize" ) ) { target->autoResize=value.toBoolean(); } else if ( !strcmp( propertyName, "main" ) ) { target->main=value.toBoolean(); } return true; }
bool GetRenderTargetProperty( JSContext *cx, Handle<JSObject *> object, Handle<jsid> id, MutableHandle<Value> value ) { RootedValue val(cx); JS_IdToValue( cx, id, MutableHandleValue(&val) ); JSString *propertyString = val.toString(); const char *propertyName=JS_EncodeString(cx, propertyString); //printf("GetRenderTargetProperty: %s\n", propertyName ); RenderTarget *target=(RenderTarget *) JS_GetPrivate( object ); if ( !strcmp( propertyName, "w" ) ) { value.set( INT_TO_JSVAL( target->w ) ); } else if ( !strcmp( propertyName, "h" ) ) { value.set( INT_TO_JSVAL( target->h ) ); } else if ( !strcmp( propertyName, "autoResize" ) ) { value.set( BOOLEAN_TO_JSVAL( target->autoResize ) ); } else if ( !strcmp( propertyName, "main" ) ) { value.set( BOOLEAN_TO_JSVAL( target->main ) ); } return true; }
bool DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, MutableHandle<JSPropertyDescriptor> desc, bool* defined) { if (desc.hasGetterObject() && desc.setter() == JS_StrictPropertyStub) { return JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING | JSREPORT_STRICT | JSREPORT_STRICT_MODE_ERROR, js_GetErrorMessage, NULL, JSMSG_GETTER_ONLY); } if (xpc::WrapperFactory::IsXrayWrapper(proxy)) { return true; } JSObject* expando = EnsureExpandoObject(cx, proxy); if (!expando) { return false; } bool dummy; return js_DefineOwnProperty(cx, expando, id, desc, &dummy); }
bool DirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id, MutableHandle<PropertyDescriptor> desc) const { assertEnteredPolicy(cx, proxy, id, SET); RootedObject target(cx, proxy->as<ProxyObject>().target()); RootedValue v(cx, desc.value()); return CheckDefineProperty(cx, target, id, v, desc.attributes(), desc.getter(), desc.setter()) && JS_DefinePropertyById(cx, target, id, v, desc.attributes(), desc.getter(), desc.setter()); }
static bool DecodeMemory(JSContext* cx, Decoder& d, ModuleGenerator& mg, MutableHandle<ArrayBufferObject*> heap) { uint32_t sectionStart; if (!d.startSection(MemoryId, §ionStart)) return Fail(cx, d, "failed to start section"); if (sectionStart == Decoder::NotStarted) return true; uint32_t initialSizePages; if (!d.readVarU32(&initialSizePages)) return Fail(cx, d, "expected initial memory size"); CheckedInt<int32_t> initialSize = initialSizePages; initialSize *= PageSize; if (!initialSize.isValid()) return Fail(cx, d, "initial memory size too big"); uint32_t maxSizePages; if (!d.readVarU32(&maxSizePages)) return Fail(cx, d, "expected initial memory size"); CheckedInt<int32_t> maxSize = maxSizePages; maxSize *= PageSize; if (!maxSize.isValid()) return Fail(cx, d, "initial memory size too big"); uint8_t exported; if (!d.readFixedU8(&exported)) return Fail(cx, d, "expected exported byte"); if (exported) { UniqueChars fieldName = DuplicateString("memory"); if (!fieldName || !mg.addMemoryExport(Move(fieldName))) return false; } if (!d.finishSection(sectionStart)) return Fail(cx, d, "memory section byte size mismatch"); bool signalsForOOB = CompileArgs(cx).useSignalHandlersForOOB; heap.set(ArrayBufferObject::createForWasm(cx, initialSize.value(), signalsForOOB)); if (!heap) return false; mg.initHeapUsage(HeapUsage::Unshared); return true; }
static bool WaiveAccessors(JSContext* cx, MutableHandle<PropertyDescriptor> desc) { if (desc.hasGetterObject() && desc.getterObject()) { RootedValue v(cx, JS::ObjectValue(*desc.getterObject())); if (!WrapperFactory::WaiveXrayAndWrap(cx, &v)) return false; desc.setGetterObject(&v.toObject()); } if (desc.hasSetterObject() && desc.setterObject()) { RootedValue v(cx, JS::ObjectValue(*desc.setterObject())); if (!WrapperFactory::WaiveXrayAndWrap(cx, &v)) return false; desc.setSetterObject(&v.toObject()); } return true; }
static bool FillMyHashMap(JSContext* cx, MutableHandle<MyHashMap> map) { for (size_t i = 0; i < 10; ++i) { RootedObject obj(cx, JS_NewObject(cx, nullptr)); RootedValue val(cx, UndefinedValue()); // Construct a unique property name to ensure that the object creates a // new shape. char buffer[2]; buffer[0] = 'a' + i; buffer[1] = '\0'; if (!JS_SetProperty(cx, obj, buffer, val)) return false; if (!map.putNew(obj->as<NativeObject>().lastProperty(), obj)) return false; } return true; }