diff -r 12ed9db481bc js/src/js.msg --- a/js/src/js.msg Mon Aug 20 09:17:32 2012 +0200 +++ b/js/src/js.msg Mon Aug 20 09:19:52 2012 +0200 @@ -358,8 +358,10 @@ MSG_DEF(JSMSG_CANT_REPORT_E_AS_NE, 30 MSG_DEF(JSMSG_CANT_REPORT_NEW, 305, 0, JSEXN_TYPEERR, "proxy can't report a new property on a non-extensible object") MSG_DEF(JSMSG_CANT_REPORT_INVALID, 306, 0, JSEXN_TYPEERR, "proxy can't report an incompatible property descriptor") MSG_DEF(JSMSG_CANT_REPORT_NE_AS_NC, 307, 0, JSEXN_TYPEERR, "proxy can't report a non-existent property as non-configurable") MSG_DEF(JSMSG_CANT_DEFINE_NEW, 308, 0, JSEXN_TYPEERR, "proxy can't define a new property on a non-extensible object") MSG_DEF(JSMSG_CANT_DEFINE_INVALID, 309, 0, JSEXN_TYPEERR, "proxy can't define an incompatible property descriptor") MSG_DEF(JSMSG_CANT_DEFINE_NE_AS_NC, 310, 0, JSEXN_TYPEERR, "proxy can't define a non-existent property as non-configurable") MSG_DEF(JSMSG_INVALID_TRAP_RESULT, 311, 2, JSEXN_TYPEERR, "trap {1} for {0} returned an invalid result") MSG_DEF(JSMSG_CANT_SKIP_NC, 312, 0, JSEXN_TYPEERR, "proxy can't skip a non-configurable property") +MSG_DEF(JSMSG_MUST_REPORT_SAME_VALUE, 313, 0, JSEXN_TYPEERR, "proxy must report the same value for a non-writable, non-configurable property") +MSG_DEF(JSMSG_MUST_REPORT_UNDEFINED, 314, 0, JSEXN_TYPEERR, "proxy must report undefined for a non-configurable accessor property without a getter") diff -r 12ed9db481bc js/src/jsproxy.cpp --- a/js/src/jsproxy.cpp Mon Aug 20 09:17:32 2012 +0200 +++ b/js/src/jsproxy.cpp Mon Aug 20 09:19:52 2012 +0200 @@ -1906,22 +1906,87 @@ ScriptedDirectProxyHandler::hasOwn(JSCon } } // step 9 *bp = !!success; return true; } +// Proxy.[[GetP]](P, Receiver) bool -ScriptedDirectProxyHandler::get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, +ScriptedDirectProxyHandler::get(JSContext *cx, JSObject *proxy_, JSObject *receiver_, jsid id_, Value *vp) { - JS_NOT_REACHED("not yet implemented"); - return false; + RootedObject proxy(cx, proxy_); + RootedObject receiver(cx, receiver_); + RootedId id(cx, id_); + + // step 1 + RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); + + // step 2 + RootedObject target(cx, GetProxyTargetObject(proxy)); + + // step 3 + RootedValue trap(cx); + if (!handler->getProperty(cx, ATOM(get), &trap)) + return false; + + // step 4 + if (trap.isUndefined()) + return DirectProxyHandler::get(cx, proxy_, receiver_, id_, vp); + + // step 5 + JSString *name = ToString(cx, IdToValue(id)); + if (!name) + return false; + Value argv[] = { + ObjectOrNullValue(target), + StringValue(name), + ObjectOrNullValue(receiver) + }; + RootedValue trapResult(cx); + if (!Invoke(cx, ObjectValue(*handler), trap, 3, argv, trapResult.address())) + return false; + + // step 6 + AutoPropertyDescriptorRooter desc(cx); + if (!GetOwnPropertyDescriptor(cx, target, id, &desc)) + return false; + + // step 7 + if (desc.obj) { + if (IsDataDescriptor(desc) && + (desc.attrs & JSPROP_PERMANENT) && + (desc.attrs & JSPROP_READONLY)) + { + bool same; + if (!SameValue(cx, *vp, desc.value, &same)) + return false; + if (!same) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MUST_REPORT_SAME_VALUE); + return false; + } + } + + if (IsAccessorDescriptor(desc) && + (desc.attrs & JSPROP_PERMANENT) && + !(desc.attrs & JSPROP_GETTER)) + { + if (!trapResult.isUndefined()) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MUST_REPORT_UNDEFINED); + return false; + } + } + } + + // step 8 + *vp = trapResult; + return true; } bool ScriptedDirectProxyHandler::set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict, Value *vp) { JS_NOT_REACHED("not yet implemented"); return false;