michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: */ michael@0: michael@0: #include "jsfriendapi.h" michael@0: #include "jsproxy.h" michael@0: michael@0: #include "jsapi-tests/tests.h" michael@0: michael@0: using namespace js; michael@0: using namespace JS; michael@0: michael@0: class CustomProxyHandler : public DirectProxyHandler { michael@0: public: michael@0: CustomProxyHandler() : DirectProxyHandler(nullptr) {} michael@0: michael@0: bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id, michael@0: MutableHandle desc) MOZ_OVERRIDE michael@0: { michael@0: return impl(cx, proxy, id, desc, false); michael@0: } michael@0: michael@0: bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id, michael@0: MutableHandle desc) MOZ_OVERRIDE michael@0: { michael@0: return impl(cx, proxy, id, desc, true); michael@0: } michael@0: michael@0: bool set(JSContext *cx, HandleObject proxy, HandleObject receiver, michael@0: HandleId id, bool strict, MutableHandleValue vp) MOZ_OVERRIDE michael@0: { michael@0: Rooted desc(cx); michael@0: if (!DirectProxyHandler::getPropertyDescriptor(cx, proxy, id, &desc)) michael@0: return false; michael@0: return SetPropertyIgnoringNamedGetter(cx, this, proxy, receiver, id, &desc, michael@0: desc.object() == proxy, strict, vp); michael@0: } michael@0: michael@0: private: michael@0: bool impl(JSContext *cx, HandleObject proxy, HandleId id, michael@0: MutableHandle desc, bool ownOnly) michael@0: { michael@0: if (JSID_IS_STRING(id)) { michael@0: bool match; michael@0: if (!JS_StringEqualsAscii(cx, JSID_TO_STRING(id), "phantom", &match)) michael@0: return false; michael@0: if (match) { michael@0: desc.object().set(proxy); michael@0: desc.attributesRef() = JSPROP_READONLY | JSPROP_ENUMERATE; michael@0: desc.value().setInt32(42); michael@0: return true; michael@0: } michael@0: } michael@0: michael@0: if (ownOnly) michael@0: return DirectProxyHandler::getOwnPropertyDescriptor(cx, proxy, id, desc); michael@0: return DirectProxyHandler::getPropertyDescriptor(cx, proxy, id, desc); michael@0: } michael@0: michael@0: }; michael@0: michael@0: CustomProxyHandler customProxyHandler; michael@0: michael@0: michael@0: BEGIN_TEST(testSetPropertyIgnoringNamedGetter_direct) michael@0: { michael@0: RootedValue protov(cx); michael@0: EVAL("Object.prototype", &protov); michael@0: michael@0: RootedValue targetv(cx); michael@0: EVAL("({})", &targetv); michael@0: michael@0: RootedObject proxyObj(cx, NewProxyObject(cx, &customProxyHandler, targetv, michael@0: &protov.toObject(), global, ProxyOptions())); michael@0: CHECK(proxyObj); michael@0: michael@0: CHECK(JS_DefineProperty(cx, global, "target", targetv, 0)); michael@0: CHECK(JS_DefineProperty(cx, global, "proxy", proxyObj, 0)); michael@0: michael@0: RootedValue v(cx); michael@0: EVAL("Object.getOwnPropertyDescriptor(proxy, 'phantom').value", &v); michael@0: CHECK_SAME(v, Int32Value(42)); michael@0: michael@0: EXEC("proxy.phantom = 123"); michael@0: EVAL("Object.getOwnPropertyDescriptor(proxy, 'phantom').value", &v); michael@0: CHECK_SAME(v, Int32Value(42)); michael@0: EVAL("target.phantom", &v); michael@0: CHECK_SAME(v, Int32Value(123)); michael@0: michael@0: return true; michael@0: } michael@0: END_TEST(testSetPropertyIgnoringNamedGetter_direct)