Mercurial > spidermonkey-playground
changeset 34:afca92a2e72e
enumeration is now supported on wrappers via JSNewEnumerateOp.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Mon, 22 Jun 2009 15:33:18 -0700 |
parents | cb058fac14fa |
children | 5899faf625d4 |
files | tcb.js wrapper.cpp |
diffstat | 2 files changed, 63 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/tcb.js Mon Jun 22 14:39:04 2009 -0700 +++ b/tcb.js Mon Jun 22 15:33:18 2009 -0700 @@ -149,8 +149,10 @@ return wrappee == other; }, - enumerate: function() { - throw new Error("Enumeration is not implemented."); + enumerate: function(wrappee, wrapper) { + // TODO: Is this secure? + for (name in wrappee) + yield name; }, iteratorObject: function(wrappee, wrapper, keysOnly) { @@ -205,6 +207,11 @@ print("module.foo() is " + module.foo()); })(); +for (name in module) + print(name); + +print("enumerate is " + enumerate(module)); + // Some unit tests. var wrapper = {};
--- a/wrapper.cpp Mon Jun 22 14:39:04 2009 -0700 +++ b/wrapper.cpp Mon Jun 22 15:33:18 2009 -0700 @@ -36,6 +36,8 @@ #include "wrapper.h" +#include "string.h" + // Reserved slot ID for the resolver (meta) object #define SLOT_RESOLVER 0 @@ -83,14 +85,52 @@ } static JSBool -enumerate(JSContext *cx, JSObject *obj) -{ - if (resolverHasMethod(cx, obj, "enumerate")) { +enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, + jsval *statep, jsid *idp) +{ + switch (enum_op) { + case JSENUMERATE_INIT: + if (resolverHasMethod(cx, obj, "enumerate")) { + if (!delegateToResolver(cx, obj, "enumerate", 0, NULL, statep)) + return JS_FALSE; + if (!JSVAL_IS_OBJECT(*statep)) { + JS_ReportError(cx, "Expected enumerate() to return an iterator."); + return JS_FALSE; + } + *idp = JSVAL_ZERO; + // TODO: Root the enumeration iterator? + return JS_TRUE; + } + // TODO: Default behavior? + JS_ReportError(cx, "Enumeration is not implemented on this object."); + return JS_FALSE; + case JSENUMERATE_NEXT: jsval rval; - if (!delegateToResolver(cx, obj, "enumerate", 0, NULL, &rval)) + JSObject *iterator = JSVAL_TO_OBJECT(*statep); + if (!JS_CallFunctionName(cx, iterator, "next", 0, NULL, &rval)) { + if (JS_IsExceptionPending(cx)) { + jsval exception; + if (!JS_GetPendingException(cx, &exception)) + return JS_FALSE; + if (!JSVAL_IS_OBJECT(exception)) + return JS_FALSE; + JSClass *klass = JS_GET_CLASS(cx, JSVAL_TO_OBJECT(exception)); + if (klass && strcmp(klass->name, "StopIteration") == 0) { + JS_ClearPendingException(cx); + *statep = JSVAL_NULL; + // TODO: Unroot the enumeration iterator? + return JS_TRUE; + } + } return JS_FALSE; + } + if (!JS_ValueToId(cx, rval, idp)) + return JS_FALSE; + return JS_TRUE; + case JSENUMERATE_DESTROY: + // TODO: Unroot the enumeration iterator? + return JS_TRUE; } - return JS_EnumerateStub(cx, obj); } static JSBool @@ -293,15 +333,15 @@ // JSClass (JSExtendedClass.base) initialization { "FlexibleWrapper", JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED | - JSCLASS_HAS_RESERVED_SLOTS(2), - addProperty, delProperty, - getProperty, setProperty, - enumerate, (JSResolveOp)resolve, - convert, JS_FinalizeStub, - NULL, checkAccess, - call, construct, - NULL, NULL, - NULL, NULL + JSCLASS_NEW_ENUMERATE | JSCLASS_HAS_RESERVED_SLOTS(2), + addProperty, delProperty, + getProperty, setProperty, + (JSEnumerateOp)enumerate, (JSResolveOp)resolve, + convert, JS_FinalizeStub, + NULL, checkAccess, + call, construct, + NULL, NULL, + NULL, NULL }, // JSExtendedClass initialization equality,