diff --git a/js/src/builtin/MapObject.cpp b/js/src/builtin/MapObject.cpp index 8b7d4f4c6bb7..05fc32d14ff5 100644 --- a/js/src/builtin/MapObject.cpp +++ b/js/src/builtin/MapObject.cpp @@ -1237,11 +1237,24 @@ MapObject::construct(JSContext *cx, unsigned argc, Value *vp) CallArgs args = CallArgsFromVp(argc, vp); if (!args.get(0).isNullOrUndefined()) { + RootedValue adderVal(cx); + if (!JSObject::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)); + FastInvokeGuard fig(cx, adderVal); + InvokeArgs &args2 = fig.args(); + ForOfIterator iter(cx); if (!iter.init(args[0])) return false; RootedValue pairVal(cx); RootedObject pairObj(cx); + AutoHashableValueRooter hkey(cx); ValueMap *map = obj->getData(); while (true) { bool done; @@ -1263,20 +1276,32 @@ MapObject::construct(JSContext *cx, unsigned argc, Value *vp) if (!JSObject::getElement(cx, pairObj, pairObj, 0, &key)) return false; - AutoHashableValueRooter hkey(cx); - if (!hkey.setValue(cx, key)) - return false; - RootedValue val(cx); if (!JSObject::getElement(cx, pairObj, pairObj, 1, &val)) return false; - RelocatableValue rval(val); - if (!map->put(hkey, rval)) { - js_ReportOutOfMemory(cx); - return false; + if (isOriginalAdder) { + if (!hkey.setValue(cx, key)) + return false; + + RelocatableValue rval(val); + if (!map->put(hkey, rval)) { + js_ReportOutOfMemory(cx); + return false; + } + WriteBarrierPost(cx->runtime(), map, key); + } else { + if (!args2.init(2)) + return false; + + args2.setCallee(adderVal); + args2.setThis(mapVal); + args2[0].set(key); + args2[1].set(val); + + if (!fig.invoke(cx)) + return false; } - WriteBarrierPost(cx->runtime(), map, key); } }