bool WrapperOwner::getPropertyKeys(JSContext* cx, HandleObject proxy, uint32_t flags, AutoIdVector& props) { ObjectId objId = idOf(proxy); ReturnStatus status; InfallibleTArray<JSIDVariant> ids; if (!SendGetPropertyKeys(objId, flags, &status, &ids)) return ipcfail(cx); LOG_STACK(); if (!ok(cx, status)) return false; for (size_t i = 0; i < ids.Length(); i++) { RootedId id(cx); if (!fromJSIDVariant(cx, ids[i], &id)) return false; if (!props.append(id)) return false; } return true; }
// ES8 rev 0c1bd3004329336774cbc90de727cd0cf5f11e93 // 7.3.17 CreateListFromArrayLike with elementTypes fixed to symbol/string. static bool CreateFilteredListFromArrayLike(JSContext* cx, HandleValue v, AutoIdVector& props) { // Step 2. RootedObject obj(cx, NonNullObjectWithName(cx, "return value of the ownKeys trap", v)); if (!obj) return false; // Step 3. uint32_t len; if (!GetLengthProperty(cx, obj, &len)) return false; // Steps 4-6. RootedValue next(cx); RootedId id(cx); uint32_t index = 0; while (index < len) { // Steps 6a-b. if (!GetElement(cx, obj, obj, index, &next)) return false; // Step 6c. if (!next.isString() && !next.isSymbol()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_OWNKEYS_STR_SYM); return false; } if (!ValueToId<CanGC>(cx, next, &id)) return false; // Step 6d. if (!props.append(id)) return false; // Step 6e. index++; } // Step 7. return true; }
// ES6 7.3.17 But elementTypes is is fixed to symbol/string. static bool CreateFilteredListFromArrayLike(JSContext* cx, HandleValue v, AutoIdVector& props) { // Step 3. RootedObject obj(cx, NonNullObject(cx, v)); if (!obj) return false; // Steps 4-5. uint32_t len; if (!GetLengthProperty(cx, obj, &len)) return false; // Steps 6-8. RootedValue next(cx); RootedId id(cx); for (uint32_t index = 0; index < len; index++) { if (!GetElement(cx, obj, obj, index, &next)) return false; if (!next.isString() && !next.isSymbol()) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_ONWKEYS_STR_SYM); return false; } // Unobservable for strings/symbols. if (!ValueToId<CanGC>(cx, next, &id)) return false; if (!props.append(id)) return false; } // Step 9. return true; }
// This function is shared between ownPropertyKeys, enumerate, and // getOwnEnumerablePropertyKeys. static bool ArrayToIdVector(JSContext *cx, HandleObject proxy, HandleObject target, HandleValue v, AutoIdVector &props, unsigned flags, JSAtom *trapName_) { MOZ_ASSERT(v.isObject()); RootedObject array(cx, &v.toObject()); RootedAtom trapName(cx, trapName_); // steps g-h uint32_t n; if (!GetLengthProperty(cx, array, &n)) return false; // steps i-k for (uint32_t i = 0; i < n; ++i) { // step i RootedValue v(cx); if (!GetElement(cx, array, array, i, &v)) return false; // step ii RootedId id(cx); if (!ValueToId<CanGC>(cx, v, &id)) return false; // step iii for (uint32_t j = 0; j < i; ++j) { if (props[j].get() == id) { ReportInvalidTrapResult(cx, proxy, trapName); return false; } } // step iv bool isFixed; if (!HasOwnProperty(cx, target, id, &isFixed)) return false; // step v bool extensible; if (!IsExtensible(cx, target, &extensible)) return false; if (!extensible && !isFixed) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_REPORT_NEW); return false; } // step vi if (!props.append(id)) return false; } // step l AutoIdVector ownProps(cx); if (!GetPropertyKeys(cx, target, flags, &ownProps)) return false; // step m for (size_t i = 0; i < ownProps.length(); ++i) { RootedId id(cx, ownProps[i]); bool found = false; for (size_t j = 0; j < props.length(); ++j) { if (props[j].get() == id) { found = true; break; } } if (found) continue; // step i bool sealed; if (!IsSealed(cx, target, id, &sealed)) return false; if (sealed) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_SKIP_NC); return false; } // step ii bool isFixed; if (!HasOwnProperty(cx, target, id, &isFixed)) return false; // step iii bool extensible; if (!IsExtensible(cx, target, &extensible)) return false; if (!extensible && isFixed) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_REPORT_E_AS_NE); return false; } } // step n return true; }