diff -r 51c86f17f7eb js/src/jsproxy.cpp --- a/js/src/jsproxy.cpp Mon Aug 20 17:00:28 2012 +0200 +++ b/js/src/jsproxy.cpp Mon Aug 20 17:01:48 2012 +0200 @@ -1727,21 +1727,59 @@ ScriptedDirectProxyHandler::delete_(JSCo } // step 8 // FIXME: API does not include a Throw parameter *bp = false; return true; } +// 12.6.4 The for-in Statement, step 6 bool -ScriptedDirectProxyHandler::enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props) +ScriptedDirectProxyHandler::enumerate(JSContext *cx, JSObject *proxy_, AutoIdVector &props) { - JS_NOT_REACHED("not yet implemented"); - return false; + RootedObject proxy(cx, proxy_); + + // step a + RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); + + // step b + RootedObject target(cx, GetProxyTargetObject(proxy)); + + // step c + RootedValue trap(cx); + if (!handler->getProperty(cx, ATOM(enumerate), &trap)) + return false; + + // step d + if (trap.isUndefined()) + return DirectProxyHandler::enumerate(cx, proxy_, props); + + // step e + Value argv[] = { + ObjectOrNullValue(target) + }; + RootedValue trapResult(cx); + if (!Invoke(cx, ObjectValue(*handler), trap, 1, argv, trapResult.address())) + return false; + + // step f + if (trapResult.isPrimitive()) { + JSAutoByteString bytes; + if (!js_AtomToPrintableString(cx, ATOM(enumerate), &bytes)) + return false; + RootedValue v(cx, ObjectOrNullValue(proxy)); + js_ReportValueError2(cx, JSMSG_INVALID_TRAP_RESULT, JSDVG_SEARCH_STACK, + v, NullPtr(), bytes.ptr()); + return false; + } + + // steps g-m are shared + // FIXME: the trap should return an iterator object, see bug 783826 + return ArrayToIdVector(cx, proxy, target, trapResult, props, ATOM(enumerate)); } bool ScriptedDirectProxyHandler::has(JSContext *cx, JSObject *proxy, jsid id, bool *bp) { JS_NOT_REACHED("not yet implemented"); return false; }