Bug 924059. Give ArrayIterator and its prototype different JSClasses so we can't confuse them for each other. r=waldo
This commit is contained in:
@@ -651,7 +651,7 @@ function ArrayIteratorIdentity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ArrayIteratorNext() {
|
function ArrayIteratorNext() {
|
||||||
// FIXME: ArrayIterator prototype should not pass this test. Bug 924059.
|
// FIXME: Cross-compartment wrapper ArrayIterator objects should pass this test. Bug 1111170.
|
||||||
if (!IsObject(this) || !IsArrayIterator(this))
|
if (!IsObject(this) || !IsArrayIterator(this))
|
||||||
ThrowError(JSMSG_INCOMPATIBLE_METHOD, "ArrayIterator", "next", ToString(this));
|
ThrowError(JSMSG_INCOMPATIBLE_METHOD, "ArrayIterator", "next", ToString(this));
|
||||||
|
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ function StringIteratorIdentity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function StringIteratorNext() {
|
function StringIteratorNext() {
|
||||||
// FIXME: Cross-compartment wrapper StringIterator objects should pass this test. Bug 924059.
|
// FIXME: Cross-compartment wrapper StringIterator objects should pass this test. Bug 1111170.
|
||||||
if (!IsObject(this) || !IsStringIterator(this))
|
if (!IsObject(this) || !IsStringIterator(this))
|
||||||
ThrowError(JSMSG_INCOMPATIBLE_METHOD, "StringIterator", "next", ToString(this));
|
ThrowError(JSMSG_INCOMPATIBLE_METHOD, "StringIterator", "next", ToString(this));
|
||||||
|
|
||||||
|
|||||||
@@ -926,6 +926,11 @@ const Class PropertyIteratorObject::class_ = {
|
|||||||
trace
|
trace
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const Class ArrayIteratorPrototypeClass = {
|
||||||
|
"Array Iterator",
|
||||||
|
JSCLASS_IMPLEMENTS_BARRIERS
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ArrayIteratorSlotIteratedObject,
|
ArrayIteratorSlotIteratedObject,
|
||||||
ArrayIteratorSlotNextIndex,
|
ArrayIteratorSlotNextIndex,
|
||||||
@@ -1335,7 +1340,7 @@ GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
|
|||||||
|
|
||||||
RootedObject proto(cx);
|
RootedObject proto(cx);
|
||||||
if (global->getSlot(ARRAY_ITERATOR_PROTO).isUndefined()) {
|
if (global->getSlot(ARRAY_ITERATOR_PROTO).isUndefined()) {
|
||||||
const Class *cls = &ArrayIteratorObject::class_;
|
const Class *cls = &ArrayIteratorPrototypeClass;
|
||||||
proto = global->createBlankPrototypeInheriting(cx, cls, *iteratorProto);
|
proto = global->createBlankPrototypeInheriting(cx, cls, *iteratorProto);
|
||||||
if (!proto || !DefinePropertiesAndFunctions(cx, proto, nullptr, array_iterator_methods))
|
if (!proto || !DefinePropertiesAndFunctions(cx, proto, nullptr, array_iterator_methods))
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
16
js/src/tests/ecma_6/Array/iterator_edge_cases.js
Normal file
16
js/src/tests/ecma_6/Array/iterator_edge_cases.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// Test that we can't confuse %ArrayIteratorPrototype% for an
|
||||||
|
// ArrayIterator object.
|
||||||
|
function TestArrayIteratorPrototypeConfusion() {
|
||||||
|
var iter = [][Symbol.iterator]();
|
||||||
|
try {
|
||||||
|
iter.next.call(Object.getPrototypeOf(iter))
|
||||||
|
throw new Error("Call did not throw");
|
||||||
|
} catch (e) {
|
||||||
|
assertEq(e instanceof TypeError, true);
|
||||||
|
assertEq(e.message, "ArrayIterator next called on incompatible [object Array Iterator]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TestArrayIteratorPrototypeConfusion();
|
||||||
|
|
||||||
|
if (typeof reportCompare === "function")
|
||||||
|
reportCompare(true, true);
|
||||||
@@ -640,7 +640,7 @@ intrinsic_NewArrayIterator(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
if (!proto)
|
if (!proto)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
JSObject *obj = NewObjectWithGivenProto(cx, proto->getClass(), proto, cx->global());
|
JSObject *obj = NewObjectWithGivenProto(cx, &ArrayIteratorObject::class_, proto, cx->global());
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user