bool MapObject::set(JSContext* cx, HandleObject obj, HandleValue k, HandleValue v) { ValueMap* map = obj->as<MapObject>().getData(); if (!map) return false; Rooted<HashableValue> key(cx); if (!key.setValue(cx, k)) return false; HeapPtr<Value> rval(v); if (!map->put(key, rval)) { ReportOutOfMemory(cx); return false; } WriteBarrierPost(cx->runtime(), map, key.value()); return true; }
bool MapObject::construct(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (!ThrowIfNotConstructing(cx, args, "Map")) return false; RootedObject proto(cx); RootedObject newTarget(cx, &args.newTarget().toObject()); if (!GetPrototypeFromConstructor(cx, newTarget, &proto)) return false; Rooted<MapObject*> obj(cx, MapObject::create(cx, proto)); if (!obj) return false; if (!args.get(0).isNullOrUndefined()) { RootedValue adderVal(cx); if (!GetProperty(cx, obj, obj, cx->names().set, &adderVal)) return false; if (!IsCallable(adderVal)) return ReportIsNotFunction(cx, adderVal); bool isOriginalAdder = IsNativeFunction(adderVal, MapObject::set); RootedValue mapVal(cx, ObjectValue(*obj)); FastCallGuard fig(cx, adderVal); InvokeArgs& args2 = fig.args(); ForOfIterator iter(cx); if (!iter.init(args[0])) return false; RootedValue pairVal(cx); RootedObject pairObj(cx); RootedValue dummy(cx); Rooted<HashableValue> hkey(cx); ValueMap* map = obj->getData(); while (true) { bool done; if (!iter.next(&pairVal, &done)) return false; if (done) break; if (!pairVal.isObject()) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_INVALID_MAP_ITERABLE, "Map"); return false; } pairObj = &pairVal.toObject(); if (!pairObj) return false; RootedValue key(cx); if (!GetElement(cx, pairObj, pairObj, 0, &key)) return false; RootedValue val(cx); if (!GetElement(cx, pairObj, pairObj, 1, &val)) return false; if (isOriginalAdder) { if (!hkey.setValue(cx, key)) return false; HeapPtr<Value> rval(val); if (!map->put(hkey, rval)) { ReportOutOfMemory(cx); return false; } WriteBarrierPost(cx->runtime(), map, key); } else { if (!args2.init(2)) return false; args2[0].set(key); args2[1].set(val); if (!fig.call(cx, adderVal, mapVal, &dummy)) return false; } } } args.rval().setObject(*obj); return true; }