Bug 804279 - Part2: Support monkey-patched/overridden adder in Set constructor. r=evilpie
☠☠ backed out by 44d7ea20541f ☠ ☠
authorTooru Fujisawa <arai_a@mac.com>
Mon, 01 Dec 2014 17:02:15 +0900
changeset 218444 a0ff17c6cdec1587e9e89d7a88f63503407d02c9
parent 218443 00fc0c2dc1110948af0cb41f0b326d8967b75b7d
child 218445 7dcbacf3d65967ed40f8d5c23a3132545ce753fe
push idunknown
push userunknown
push dateunknown
reviewersevilpie
bugs804279
milestone37.0a1
Bug 804279 - Part2: Support monkey-patched/overridden adder in Set constructor. r=evilpie
js/src/builtin/MapObject.cpp
js/src/vm/CommonPropertyNames.h
--- 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") \