mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Create a JSClass hook to allow object classes to easily support custom iteration without having to override __iterator__ in a resolve hook. bug 393306, r+a=brendan
This commit is contained in:
parent
eaabef106d
commit
6426c64ef1
@ -1214,11 +1214,11 @@ struct JSExtendedClass {
|
||||
JSEqualityOp equality;
|
||||
JSObjectOp outerObject;
|
||||
JSObjectOp innerObject;
|
||||
JSIteratorOp iteratorObject;
|
||||
void (*reserved0)();
|
||||
void (*reserved1)();
|
||||
void (*reserved2)();
|
||||
void (*reserved3)();
|
||||
void (*reserved4)();
|
||||
};
|
||||
|
||||
#define JSCLASS_HAS_PRIVATE (1<<0) /* objects have private slot */
|
||||
@ -1287,7 +1287,7 @@ struct JSExtendedClass {
|
||||
|
||||
/* Initializer for unused members of statically initialized JSClass structs. */
|
||||
#define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,0,0,0
|
||||
#define JSCLASS_NO_RESERVED_MEMBERS 0,0,0,0,0
|
||||
#define JSCLASS_NO_RESERVED_MEMBERS 0,0,0,0
|
||||
|
||||
/* For detailed comments on these function pointer types, see jspubtd.h. */
|
||||
struct JSObjectOps {
|
||||
|
@ -334,6 +334,8 @@ js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp)
|
||||
JSObject *obj;
|
||||
JSTempValueRooter tvr;
|
||||
JSAtom *atom;
|
||||
JSClass *clasp;
|
||||
JSExtendedClass *xclasp;
|
||||
JSBool ok;
|
||||
JSObject *iterobj;
|
||||
jsval arg;
|
||||
@ -370,47 +372,60 @@ js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp)
|
||||
JS_ASSERT(obj);
|
||||
JS_PUSH_TEMP_ROOT_OBJECT(cx, obj, &tvr);
|
||||
|
||||
atom = cx->runtime->atomState.iteratorAtom;
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
if (OBJECT_IS_XML(cx, obj)) {
|
||||
if (!js_GetXMLFunction(cx, obj, ATOM_TO_JSID(atom), vp))
|
||||
goto bad;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (!OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp))
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_VOID(*vp)) {
|
||||
default_iter:
|
||||
/*
|
||||
* Fail over to the default enumerating native iterator.
|
||||
*
|
||||
* Create iterobj with a NULL parent to ensure that we use the correct
|
||||
* scope chain to lookup the iterator's constructor. Since we use the
|
||||
* parent slot to keep track of the iterable, we must fix it up after.
|
||||
*/
|
||||
iterobj = js_NewObject(cx, &js_IteratorClass, NULL, NULL);
|
||||
clasp = OBJ_GET_CLASS(cx, obj);
|
||||
if ((clasp->flags & JSCLASS_IS_EXTENDED) &&
|
||||
(xclasp = (JSExtendedClass *) clasp)->iteratorObject) {
|
||||
iterobj = xclasp->iteratorObject(cx, obj, !(flags & JSITER_FOREACH));
|
||||
if (!iterobj)
|
||||
goto bad;
|
||||
|
||||
/* Store iterobj in *vp to protect it from GC (callers must root vp). */
|
||||
*vp = OBJECT_TO_JSVAL(iterobj);
|
||||
|
||||
if (!InitNativeIterator(cx, iterobj, obj, flags))
|
||||
goto bad;
|
||||
} else {
|
||||
arg = BOOLEAN_TO_JSVAL((flags & JSITER_FOREACH) == 0);
|
||||
if (!js_InternalInvoke(cx, obj, *vp, JSINVOKE_ITERATOR, 1, &arg, vp))
|
||||
goto bad;
|
||||
if (JSVAL_IS_PRIMITIVE(*vp)) {
|
||||
const char *printable = js_AtomToPrintableString(cx, atom);
|
||||
if (printable) {
|
||||
js_ReportValueError2(cx, JSMSG_BAD_ITERATOR_RETURN,
|
||||
JSDVG_SEARCH_STACK, *vp, NULL, printable);
|
||||
atom = cx->runtime->atomState.iteratorAtom;
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
if (OBJECT_IS_XML(cx, obj)) {
|
||||
if (!js_GetXMLFunction(cx, obj, ATOM_TO_JSID(atom), vp))
|
||||
goto bad;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (!OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp))
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_VOID(*vp)) {
|
||||
default_iter:
|
||||
/*
|
||||
* Fail over to the default enumerating native iterator.
|
||||
*
|
||||
* Create iterobj with a NULL parent to ensure that we use the
|
||||
* correct scope chain to lookup the iterator's constructor. Since
|
||||
* we use the parent slot to keep track of the iterable, we must
|
||||
* fix it up after.
|
||||
*/
|
||||
iterobj = js_NewObject(cx, &js_IteratorClass, NULL, NULL);
|
||||
if (!iterobj)
|
||||
goto bad;
|
||||
|
||||
/* Store in *vp to protect it from GC (callers must root vp). */
|
||||
*vp = OBJECT_TO_JSVAL(iterobj);
|
||||
|
||||
if (!InitNativeIterator(cx, iterobj, obj, flags))
|
||||
goto bad;
|
||||
} else {
|
||||
arg = BOOLEAN_TO_JSVAL((flags & JSITER_FOREACH) == 0);
|
||||
if (!js_InternalInvoke(cx, obj, *vp, JSINVOKE_ITERATOR, 1, &arg,
|
||||
vp)) {
|
||||
goto bad;
|
||||
}
|
||||
if (JSVAL_IS_PRIMITIVE(*vp)) {
|
||||
const char *printable = js_AtomToPrintableString(cx, atom);
|
||||
if (printable) {
|
||||
js_ReportValueError2(cx, JSMSG_BAD_ITERATOR_RETURN,
|
||||
JSDVG_SEARCH_STACK, *vp, NULL,
|
||||
printable);
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -524,6 +524,14 @@ typedef JSBool
|
||||
typedef JSObject *
|
||||
(* JS_DLL_CALLBACK JSObjectOp)(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Hook that creates an iterator object for a given object. Returns the
|
||||
* iterator object or null if an error or exception was thrown on cx.
|
||||
*/
|
||||
typedef JSObject *
|
||||
(* JS_DLL_CALLBACK JSIteratorOp)(JSContext *cx, JSObject *obj,
|
||||
JSBool keysonly);
|
||||
|
||||
/*
|
||||
* A generic type for functions taking a context, object, and property, with
|
||||
* no return value. Used by JSObjectOps.dropProperty currently (see above,
|
||||
|
Loading…
Reference in New Issue
Block a user