Bug 784400 - Enable cloning of object literals within functions. r=luke
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -395,18 +395,17 @@ FetchName(JSContext *cx, HandleObject ob
}
return true;
}
inline bool
IntrinsicNameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, MutableHandleValue vp)
{
JSOp op = JSOp(*pc);
- RootedPropertyName name(cx);
- name = GetNameFromBytecode(cx, script, pc, op);
+ RootedPropertyName name(cx, GetNameFromBytecode(cx, script, pc, op));
cx->global()->getIntrinsicValue(cx, name, vp);
return true;
}
inline bool
NameOperation(JSContext *cx, jsbytecode *pc, MutableHandleValue vp)
{
RootedObject obj(cx, cx->stack.currentScriptedScopeChain());
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2647,16 +2647,24 @@ js::CloneObject(JSContext *cx, HandleObj
JS_ASSERT(obj->isProxy());
if (!CopySlots(cx, obj, clone))
return NULL;
}
return clone;
}
+JSObject *
+js::CloneObjectLiteral(JSContext *cx, HandleObject parent, HandleObject srcObj)
+{
+ Rooted<TypeObject*> typeObj(cx, cx->global()->getOrCreateObjectPrototype(cx)->getNewType(cx));
+ RootedShape shape(cx, srcObj->lastProperty());
+ return NewReshapedObject(cx, typeObj, parent, srcObj->getAllocKind(), shape);
+}
+
struct JSObject::TradeGutsReserved {
Vector<Value> avals;
Vector<Value> bvals;
int newafixed;
int newbfixed;
Shape *newashape;
Shape *newbshape;
HeapSlot *newaslots;
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1385,16 +1385,19 @@ ToObject(JSContext *cx, HandleValue vp)
JS_ALWAYS_INLINE JSObject *
ToObjectFromStack(JSContext *cx, HandleValue vp)
{
if (vp.isObject())
return &vp.toObject();
return ToObjectSlow(cx, vp, true);
}
+extern JSObject *
+CloneObjectLiteral(JSContext *cx, HandleObject parent, HandleObject srcObj);
+
} /* namespace js */
extern void
js_GetObjectSlotName(JSTracer *trc, char *buf, size_t bufsize);
extern JSBool
js_ReportGetterOnlyAssignment(JSContext *cx);
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -2123,27 +2123,35 @@ js::CloneScript(JSContext *cx, HandleObj
RootedObject enclosingScope(cx);
if (StaticBlockObject *enclosingBlock = innerBlock->enclosingBlock())
enclosingScope = objects[FindBlockIndex(src, *enclosingBlock)];
else
enclosingScope = fun;
clone = CloneStaticBlockObject(cx, enclosingScope, innerBlock);
- } else {
+ } else if (obj->isFunction()) {
RootedFunction innerFun(cx, obj->toFunction());
StaticScopeIter ssi(innerFun->script()->enclosingStaticScope());
RootedObject enclosingScope(cx);
if (!ssi.done() && ssi.type() == StaticScopeIter::BLOCK)
enclosingScope = objects[FindBlockIndex(src, ssi.block())];
else
enclosingScope = fun;
clone = CloneInterpretedFunction(cx, enclosingScope, innerFun);
+ } else {
+ /*
+ * Clone object literals emitted for the JSOP_NEWOBJECT opcode. We only emit that
+ * instead of the less-optimized JSOP_NEWINIT for self-hosted code or code compiled
+ * with JSOPTION_COMPILE_N_GO set. As we don't clone the latter type of code, this
+ * case should only ever be hit when cloning objects from self-hosted code.
+ */
+ clone = CloneObjectLiteral(cx, cx->global(), obj);
}
if (!clone || !objects.append(clone))
return NULL;
}
}
/* RegExps */