зеркало из https://github.com/mozilla/gecko-dev.git
[INFER] Don't change prototype of new objects when reusing type in Array.{slice,splice,concat}. bug 683140.
This commit is contained in:
Родитель
5798d2c76d
Коммит
b29901f2bf
|
@ -0,0 +1,13 @@
|
|||
|
||||
var g = newGlobal("same-compartment");
|
||||
g.eval("this.f = function(a) {" +
|
||||
"assertEq(a instanceof Array, false);" +
|
||||
"a = Array.prototype.slice.call(a);" +
|
||||
"assertEq(a instanceof Array, true); }");
|
||||
g.f([1, 2, 3]);
|
||||
|
||||
var g2 = newGlobal("new-compartment");
|
||||
g2.a = g2.Array(10);
|
||||
assertEq(g2.a instanceof Array, false);
|
||||
g2.a = Array.prototype.slice(g2.a);
|
||||
assertEq(g2.a instanceof Array, true);
|
|
@ -2511,6 +2511,21 @@ array_unshift(JSContext *cx, uintN argc, Value *vp)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
TryReuseArrayType(JSObject *obj, JSObject *nobj)
|
||||
{
|
||||
/*
|
||||
* Try to change the type of a newly created array nobj to the same type
|
||||
* as obj. This can only be performed if the original object is an array
|
||||
* and has the same prototype.
|
||||
*/
|
||||
JS_ASSERT(nobj->isDenseArray());
|
||||
JS_ASSERT(nobj->type() == nobj->getProto()->newType);
|
||||
|
||||
if (obj->isArray() && !obj->hasSingletonType() && obj->getProto() == nobj->getProto())
|
||||
nobj->setType(obj->type());
|
||||
}
|
||||
|
||||
static JSBool
|
||||
array_splice(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
|
@ -2521,24 +2536,11 @@ array_splice(JSContext *cx, uintN argc, Value *vp)
|
|||
jsuint length, begin, end, count, delta, last;
|
||||
JSBool hole;
|
||||
|
||||
/*
|
||||
* Get the type of the result object: the original type when splicing an
|
||||
* array, a generic array type otherwise.
|
||||
*/
|
||||
TypeObject *type;
|
||||
if (obj->isArray() && !obj->hasSingletonType()) {
|
||||
type = obj->type();
|
||||
} else {
|
||||
type = GetTypeNewObject(cx, JSProto_Array);
|
||||
if (!type)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Create a new array value to return. */
|
||||
JSObject *obj2 = NewDenseEmptyArray(cx);
|
||||
if (!obj2)
|
||||
return JS_FALSE;
|
||||
obj2->setType(type);
|
||||
TryReuseArrayType(obj, obj2);
|
||||
vp->setObject(*obj2);
|
||||
|
||||
/* Nothing to do if no args. Otherwise get length. */
|
||||
|
@ -2697,8 +2699,7 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
|
|||
nobj = NewDenseCopiedArray(cx, initlen, vector);
|
||||
if (!nobj)
|
||||
return JS_FALSE;
|
||||
if (nobj->getProto() == aobj->getProto() && !aobj->hasSingletonType())
|
||||
nobj->setType(aobj->type());
|
||||
TryReuseArrayType(aobj, nobj);
|
||||
nobj->setArrayLength(cx, length);
|
||||
if (!aobj->isPackedDenseArray())
|
||||
nobj->markDenseArrayNotPacked(cx);
|
||||
|
@ -2801,22 +2802,12 @@ array_slice(JSContext *cx, uintN argc, Value *vp)
|
|||
if (begin > end)
|
||||
begin = end;
|
||||
|
||||
/* Get the type object for the returned array, as for array_splice. */
|
||||
TypeObject *type;
|
||||
if (obj->isArray() && !obj->hasSingletonType()) {
|
||||
type = obj->type();
|
||||
} else {
|
||||
type = GetTypeNewObject(cx, JSProto_Array);
|
||||
if (!type)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (obj->isDenseArray() && end <= obj->getDenseArrayInitializedLength() &&
|
||||
!js_PrototypeHasIndexedProperties(cx, obj)) {
|
||||
nobj = NewDenseCopiedArray(cx, end - begin, obj->getDenseArrayElements() + begin);
|
||||
if (!nobj)
|
||||
return JS_FALSE;
|
||||
nobj->setType(type);
|
||||
TryReuseArrayType(obj, nobj);
|
||||
if (!obj->isPackedDenseArray())
|
||||
nobj->markDenseArrayNotPacked(cx);
|
||||
vp->setObject(*nobj);
|
||||
|
@ -2827,7 +2818,7 @@ array_slice(JSContext *cx, uintN argc, Value *vp)
|
|||
nobj = NewDenseAllocatedArray(cx, end - begin);
|
||||
if (!nobj)
|
||||
return JS_FALSE;
|
||||
nobj->setType(type);
|
||||
TryReuseArrayType(obj, nobj);
|
||||
vp->setObject(*nobj);
|
||||
|
||||
AutoValueRooter tvr(cx);
|
||||
|
|
Загрузка…
Ссылка в новой задаче