Bug 1183153 - Give generator function groups the correct builtin prototype. r=Waldo
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 26 Aug 2015 11:02:15 -0400
changeset 291993 60707ba97960d5d92bb861636ee06ef4c06173b6
parent 291992 cbf83a6ab5e6c89f29f5a29b473fbac4c3f50124
child 291994 51819c4396b4ce51115785f4fab935880d41ec9f
push idunknown
push userunknown
push dateunknown
reviewersWaldo
bugs1183153
milestone43.0a1
Bug 1183153 - Give generator function groups the correct builtin prototype. r=Waldo
js/src/jsobj.cpp
js/src/jsobj.h
js/src/vm/HelperThreads.cpp
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2024,18 +2024,18 @@ js::GetBuiltinPrototype(ExclusiveContext
     Rooted<GlobalObject*> global(cx, cx->global());
     if (!MaybeResolveConstructor(cx, global, key))
         return false;
 
     protop.set(&global->getPrototype(key).toObject());
     return true;
 }
 
-static bool
-IsStandardPrototype(JSObject* obj, JSProtoKey key)
+bool
+js::IsStandardPrototype(JSObject* obj, JSProtoKey key)
 {
     GlobalObject& global = obj->global();
     Value v = global.getPrototype(key);
     return v.isObject() && obj == &v.toObject();
 }
 
 JSProtoKey
 JS::IdentifyStandardInstance(JSObject* obj)
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1075,16 +1075,19 @@ GetBuiltinPrototype(ExclusiveContext* cx
 
 JSObject*
 GetBuiltinPrototypePure(GlobalObject* global, JSProtoKey protoKey);
 
 extern bool
 SetClassAndProto(JSContext* cx, HandleObject obj,
                  const Class* clasp, Handle<TaggedProto> proto);
 
+extern bool
+IsStandardPrototype(JSObject* obj, JSProtoKey key);
+
 } /* namespace js */
 
 /*
  * Select Object.prototype method names shared between jsapi.cpp and jsobj.cpp.
  */
 extern const char js_watch_str[];
 extern const char js_unwatch_str[];
 extern const char js_hasOwnProperty_str[];
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -913,17 +913,18 @@ GlobalHelperThreadState::finishParseTask
 
     // Make sure we have all the constructors we need for the prototype
     // remapping below, since we can't GC while that's happening.
     Rooted<GlobalObject*> global(cx, &cx->global()->as<GlobalObject>());
     if (!EnsureConstructor(cx, global, JSProto_Object) ||
         !EnsureConstructor(cx, global, JSProto_Array) ||
         !EnsureConstructor(cx, global, JSProto_Function) ||
         !EnsureConstructor(cx, global, JSProto_RegExp) ||
-        !EnsureConstructor(cx, global, JSProto_Iterator))
+        !EnsureConstructor(cx, global, JSProto_Iterator) ||
+        !EnsureConstructor(cx, global, JSProto_GeneratorFunction))
     {
         LeaveParseTaskZone(rt, parseTask);
         return nullptr;
     }
 
     mergeParseTaskCompartment(rt, parseTask, global, cx->compartment());
 
     if (!parseTask->finish(cx))
@@ -977,21 +978,28 @@ GlobalHelperThreadState::mergeParseTaskC
          iter.next())
     {
         ObjectGroup* group = iter.get<ObjectGroup>();
         TaggedProto proto(group->proto());
         if (!proto.isObject())
             continue;
 
         JSProtoKey key = JS::IdentifyStandardPrototype(proto.toObject());
-        if (key == JSProto_Null)
-            continue;
+        if (key == JSProto_Null) {
+            // Generator functions don't have Function.prototype as prototype
+            // but a different function object, so IdentifyStandardPrototype
+            // doesn't work. Just special-case it here.
+            if (IsStandardPrototype(proto.toObject(), JSProto_GeneratorFunction))
+                key = JSProto_GeneratorFunction;
+            else
+                continue;
+        }
         MOZ_ASSERT(key == JSProto_Object || key == JSProto_Array ||
                    key == JSProto_Function || key == JSProto_RegExp ||
-                   key == JSProto_Iterator);
+                   key == JSProto_Iterator || key == JSProto_GeneratorFunction);
 
         JSObject* newProto = GetBuiltinPrototypePure(global, key);
         MOZ_ASSERT(newProto);
 
         group->setProtoUnchecked(TaggedProto(newProto));
     }
 
     // Move the parsed script and all its contents into the desired compartment.