Bug 804279 - Part2: Support monkey-patched/overridden adder in Set constructor. r=evilpie
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -1821,35 +1821,60 @@ bool
SetObject::construct(JSContext *cx, unsigned argc, Value *vp)
{
Rooted<SetObject*> obj(cx, SetObject::create(cx));
if (!obj)
return false;
CallArgs args = CallArgsFromVp(argc, vp);
if (!args.get(0).isNullOrUndefined()) {
+ RootedValue adderVal(cx);
+ if (!JSObject::getProperty(cx, obj, obj, cx->names().add, &adderVal))
+ return false;
+
+ if (!IsCallable(adderVal))
+ return ReportIsNotFunction(cx, adderVal);
+
+ bool isOriginalAdder = IsNativeFunction(adderVal, SetObject::add);
+ RootedValue setVal(cx, ObjectValue(*obj));
+ FastInvokeGuard fig(cx, adderVal);
+ InvokeArgs &args2 = fig.args();
+
RootedValue keyVal(cx);
ForOfIterator iter(cx);
if (!iter.init(args[0]))
return false;
AutoHashableValueRooter key(cx);
ValueSet *set = obj->getData();
while (true) {
bool done;
if (!iter.next(&keyVal, &done))
return false;
if (done)
break;
- if (!key.setValue(cx, keyVal))
- return false;
- if (!set->put(key)) {
- js_ReportOutOfMemory(cx);
- return false;
+
+ if (isOriginalAdder) {
+ if (!key.setValue(cx, keyVal))
+ return false;
+ if (!set->put(key)) {
+ js_ReportOutOfMemory(cx);
+ return false;
+ }
+ WriteBarrierPost(cx->runtime(), set, keyVal);
+ } else {
+ if (!args2.init(1))
+ return false;
+
+ args2.setCallee(adderVal);
+ args2.setThis(setVal);
+ args2[0].set(keyVal);
+
+ if (!fig.invoke(cx))
+ return false;
}
- WriteBarrierPost(cx->runtime(), set, keyVal);
}
}
args.rval().setObject(*obj);
return true;
}
bool
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -7,16 +7,17 @@
/* A higher-order macro for enumerating all cached property names. */
#ifndef vm_CommonPropertyNames_h
#define vm_CommonPropertyNames_h
#include "jsprototypes.h"
#define FOR_EACH_COMMON_PROPERTYNAME(macro) \
+ macro(add, add, "add") \
macro(anonymous, anonymous, "anonymous") \
macro(Any, Any, "Any") \
macro(apply, apply, "apply") \
macro(arguments, arguments, "arguments") \
macro(as, as, "as") \
macro(ArrayIteratorNext, ArrayIteratorNext, "ArrayIteratorNext") \
macro(ArrayType, ArrayType, "ArrayType") \
macro(ArrayValues, ArrayValues, "ArrayValues") \