Don't wrap StopIteration singleton, just translate it to the current global's StopIteration object and freeze StopIteration at birth (606573, r=mrbkap).

This commit is contained in:
Andreas Gal 2010-10-23 16:24:32 -07:00
Родитель 19087d1172
Коммит 8f3f417a80
4 изменённых файлов: 31 добавлений и 16 удалений

Просмотреть файл

@ -1718,6 +1718,10 @@ struct JSClass {
#define JSCLASS_MARK_IS_TRACE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+3))
#define JSCLASS_INTERNAL_FLAG2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4))
/* Indicate whether the proto or ctor should be frozen. */
#define JSCLASS_FREEZE_PROTO (1<<(JSCLASS_HIGH_FLAGS_SHIFT+5))
#define JSCLASS_FREEZE_CTOR (1<<(JSCLASS_HIGH_FLAGS_SHIFT+6))
/* Additional global reserved slots, beyond those for standard prototypes. */
#define JSRESERVED_GLOBAL_SLOTS_COUNT 3
#define JSRESERVED_GLOBAL_THIS (JSProto_LIMIT * 3)

Просмотреть файл

@ -38,9 +38,10 @@
*
* ***** END LICENSE BLOCK ***** */
#include "jscntxt.h"
#include "jscompartment.h"
#include "jsgc.h"
#include "jscntxt.h"
#include "jsiter.h"
#include "jsproxy.h"
#include "jsscope.h"
#include "methodjit/PolyIC.h"
@ -143,6 +144,10 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
if (obj->compartment() == this)
return true;
/* Translate StopIteration singleton. */
if (obj->getClass() == &js_StopIterationClass)
return js_FindClassObject(cx, NULL, JSProto_StopIteration, vp);
/* Don't unwrap an outer window proxy. */
if (!obj->getClass()->ext.innerObject) {
obj = vp->toObject().unwrap(&flags);

Просмотреть файл

@ -624,6 +624,16 @@ GetIterator(JSContext *cx, JSObject *obj, uintN flags, Value *vp)
bool keysOnly = (flags == JSITER_ENUMERATE);
if (obj) {
/* Enumerate Iterator.prototype directly. */
JSIteratorOp op = obj->getClass()->ext.iteratorObject;
if (op && (obj->getClass() != &js_IteratorClass || obj->getNativeIterator())) {
JSObject *iterobj = op(cx, obj, !(flags & JSITER_FOREACH));
if (!iterobj)
return false;
vp->setObject(*iterobj);
return true;
}
if (keysOnly) {
/*
* Check to see if this is the same as the most recent object which
@ -813,8 +823,7 @@ js_ValueToIterator(JSContext *cx, uintN flags, Value *vp)
if ((flags & JSITER_ENUMERATE)) {
if (!js_ValueToObjectOrNull(cx, *vp, &obj))
return false;
if (!obj)
return GetIterator(cx, NULL, flags, vp);
/* fall through */
} else {
obj = js_ValueToNonNullObject(cx, *vp);
if (!obj)
@ -822,18 +831,6 @@ js_ValueToIterator(JSContext *cx, uintN flags, Value *vp)
}
}
AutoObjectRooter tvr(cx, obj);
/* Enumerate Iterator.prototype directly. */
JSIteratorOp op = obj->getClass()->ext.iteratorObject;
if (op && (obj->getClass() != &js_IteratorClass || obj->getNativeIterator())) {
JSObject *iterobj = op(cx, obj, !(flags & JSITER_FOREACH));
if (!iterobj)
return false;
vp->setObject(*iterobj);
return true;
}
return GetIterator(cx, obj, flags, vp);
}
@ -1084,7 +1081,9 @@ stopiter_hasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
Class js_StopIterationClass = {
js_StopIteration_str,
JSCLASS_HAS_CACHED_PROTO(JSProto_StopIteration),
JSCLASS_HAS_CACHED_PROTO(JSProto_StopIteration) |
JSCLASS_FREEZE_PROTO |
JSCLASS_FREEZE_CTOR,
PropertyStub, /* addProperty */
PropertyStub, /* delProperty */
PropertyStub, /* getProperty */

Просмотреть файл

@ -3680,6 +3680,13 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
if (!proto->getEmptyShape(cx, proto->clasp, FINALIZE_OBJECT0))
goto bad;
if (clasp->flags & (JSCLASS_FREEZE_PROTO|JSCLASS_FREEZE_CTOR)) {
if (proto && (clasp->flags & JSCLASS_FREEZE_PROTO) && !proto->freeze(cx))
goto bad;
if (ctor && (clasp->flags & JSCLASS_FREEZE_CTOR) && !ctor->freeze(cx))
goto bad;
}
/* If this is a standard class, cache its prototype. */
if (key != JSProto_Null && !js_SetClassObject(cx, obj, key, ctor, proto))
goto bad;