static bool EnumerateExtraProperties(JSContext* cx, HandleObject obj, unsigned flags, Maybe<IdSet>& ht, AutoIdVector* props) { MOZ_ASSERT(obj->getOps()->enumerate); AutoIdVector properties(cx); bool enumerableOnly = !(flags & JSITER_HIDDEN); if (!obj->getOps()->enumerate(cx, obj, properties, enumerableOnly)) return false; RootedId id(cx); for (size_t n = 0; n < properties.length(); n++) { id = properties[n]; // The enumerate hook does not indicate whether the properties // it returns are enumerable or not. Since we already passed // `enumerableOnly` to the hook to filter out non-enumerable // properties, it doesn't really matter what we pass here. bool enumerable = true; if (!Enumerate(cx, obj, id, enumerable, flags, ht, props)) return false; } return true; }
static inline bool Enumerate(JSContext* cx, HandleObject pobj, jsid id, bool enumerable, unsigned flags, Maybe<IdSet>& ht, AutoIdVector* props) { if (!(flags & JSITER_OWNONLY) || pobj->is<ProxyObject>() || pobj->getOps()->enumerate) { if (!ht) { ht.emplace(cx); // Most of the time there are only a handful of entries. if (!ht->init(5)) return false; } // If we've already seen this, we definitely won't add it. IdSet::AddPtr p = ht->lookupForAdd(id); if (MOZ_UNLIKELY(!!p)) return true; // It's not necessary to add properties to the hash table at the end of // the prototype chain, but custom enumeration behaviors might return // duplicated properties, so always add in such cases. if ((pobj->is<ProxyObject>() || pobj->getProto() || pobj->getOps()->enumerate) && !ht->add(p, id)) return false; } // Symbol-keyed properties and nonenumerable properties are skipped unless // the caller specifically asks for them. A caller can also filter out // non-symbols by asking for JSITER_SYMBOLSONLY. if (JSID_IS_SYMBOL(id) ? !(flags & JSITER_SYMBOLS) : (flags & JSITER_SYMBOLSONLY)) return true; if (!enumerable && !(flags & JSITER_HIDDEN)) return true; return props->append(id); }
bool SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value, bool strict, jsbytecode *pc) { RootedValue v(cx, value); RootedId id(cx, NameToId(name)); JSOp op = JSOp(*pc); if (op == JSOP_SETALIASEDVAR) { // Aliased var assigns ignore readonly attributes on the property, as // required for initializing 'const' closure variables. Shape *shape = obj->nativeLookup(cx, name); JS_ASSERT(shape && shape->hasSlot()); obj->nativeSetSlotWithType(cx, shape, value); return true; } if (MOZ_LIKELY(!obj->getOps()->setProperty)) { return baseops::SetPropertyHelper<SequentialExecution>( cx, obj, obj, id, (op == JSOP_SETNAME || op == JSOP_SETGNAME) ? baseops::Unqualified : baseops::Qualified, &v, strict); } return JSObject::setGeneric(cx, obj, obj, id, &v, strict); }
bool SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value, bool strict, jsbytecode *pc) { RootedValue v(cx, value); RootedId id(cx, NameToId(name)); JSOp op = JSOp(*pc); if (op == JSOP_SETALIASEDVAR) { // Aliased var assigns ignore readonly attributes on the property, as // required for initializing 'const' closure variables. Shape *shape = obj->as<NativeObject>().lookup(cx, name); MOZ_ASSERT(shape && shape->hasSlot()); obj->as<NativeObject>().setSlotWithType(cx, shape, value); return true; } if (MOZ_LIKELY(!obj->getOps()->setProperty)) { return NativeSetProperty( cx, obj.as<NativeObject>(), obj.as<NativeObject>(), id, (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME || op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME) ? Unqualified : Qualified, &v, strict); } return SetProperty(cx, obj, obj, id, &v, strict); }
static inline bool Enumerate(JSContext *cx, HandleObject pobj, jsid id, bool enumerable, unsigned flags, Maybe<IdSet>& ht, AutoIdVector *props) { // We implement __proto__ using a property on |Object.prototype|, but // because __proto__ is highly deserving of removal, we don't want it to // show up in property enumeration, even if only for |Object.prototype| // (think introspection by Prototype-like frameworks that add methods to // the built-in prototypes). So exclude __proto__ if the object where the // property was found has no [[Prototype]] and might be |Object.prototype|. if (MOZ_UNLIKELY(!pobj->getTaggedProto().isObject() && JSID_IS_ATOM(id, cx->names().proto))) return true; if (!(flags & JSITER_OWNONLY) || pobj->is<ProxyObject>() || pobj->getOps()->enumerate) { if (!ht) { ht.emplace(cx); // Most of the time there are only a handful of entries. if (!ht->init(5)) return false; } // If we've already seen this, we definitely won't add it. IdSet::AddPtr p = ht->lookupForAdd(id); if (MOZ_UNLIKELY(!!p)) return true; // It's not necessary to add properties to the hash table at the end of // the prototype chain, but custom enumeration behaviors might return // duplicated properties, so always add in such cases. if ((pobj->is<ProxyObject>() || pobj->getProto() || pobj->getOps()->enumerate) && !ht->add(p, id)) return false; } // Symbol-keyed properties and nonenumerable properties are skipped unless // the caller specifically asks for them. A caller can also filter out // non-symbols by asking for JSITER_SYMBOLSONLY. if (JSID_IS_SYMBOL(id) ? !(flags & JSITER_SYMBOLS) : (flags & JSITER_SYMBOLSONLY)) return true; if (!enumerable && !(flags & JSITER_HIDDEN)) return true; return props->append(id); }
bool SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value, bool strict, bool isSetName) { RootedValue v(cx, value); RootedId id(cx, NameToId(name)); if (JS_LIKELY(!obj->getOps()->setProperty)) { unsigned defineHow = isSetName ? DNP_UNQUALIFIED : 0; return baseops::SetPropertyHelper(cx, obj, obj, id, defineHow, &v, strict); } return JSObject::setGeneric(cx, obj, obj, id, &v, strict); }
bool jit::SetPropertyPar(ForkJoinSlice *slice, HandleObject obj, HandlePropertyName name, HandleValue value, bool strict, jsbytecode *pc) { JS_ASSERT(slice->isThreadLocal(obj)); if (*pc == JSOP_SETALIASEDVAR) { // See comment in jit::SetProperty. Shape *shape = obj->nativeLookupPure(name); JS_ASSERT(shape && shape->hasSlot()); return obj->nativeSetSlotIfHasType(shape, value); } // Fail early on hooks. if (obj->getOps()->setProperty) return TP_RETRY_SEQUENTIALLY; RootedValue v(slice, value); RootedId id(slice, NameToId(name)); return baseops::SetPropertyHelper<ParallelExecution>(slice, obj, obj, id, 0, &v, strict); }
bool SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value, bool strict, int jsop) { RootedValue v(cx, value); RootedId id(cx, NameToId(name)); if (jsop == JSOP_SETALIASEDVAR) { // Aliased var assigns ignore readonly attributes on the property, as // required for initializing 'const' closure variables. Shape *shape = obj->nativeLookup(cx, name); JS_ASSERT(shape && shape->hasSlot()); JSObject::nativeSetSlotWithType(cx, obj, shape, value); return true; } if (JS_LIKELY(!obj->getOps()->setProperty)) { unsigned defineHow = (jsop == JSOP_SETNAME || jsop == JSOP_SETGNAME) ? DNP_UNQUALIFIED : 0; return baseops::SetPropertyHelper(cx, obj, obj, id, defineHow, &v, strict); } return JSObject::setGeneric(cx, obj, obj, id, &v, strict); }