Bug 789897 - Implement a preventExtensions trap for proxies. Patch is a semi-tag-team effort with jwalden. r=jwalden, r=ejpbruel, r=bholley, r=two-turtle-doves-and-a-partridge-in-a-pear-tree

--HG--
extra : rebase_source : 03b1b90c727ecc6a5d9d8cd769423f0a8f6efde4
This commit is contained in:
Eddy Bruel 2013-03-22 19:43:12 -07:00
parent 60d09841fd
commit 7b5ad4785e
9 changed files with 58 additions and 4 deletions

View File

@ -315,6 +315,14 @@ BaseProxyHandler::isExtensible(JSObject *proxy)
return true;
}
bool
BaseProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy)
{
// See above.
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CHANGE_EXTENSIBILITY);
return false;
}
bool
BaseProxyHandler::call(JSContext *cx, HandleObject proxy, unsigned argc,
Value *vp)
@ -651,6 +659,13 @@ DirectProxyHandler::isExtensible(JSObject *proxy)
return GetProxyTargetObject(proxy)->isExtensible();
}
bool
DirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy)
{
RootedObject target(cx, GetProxyTargetObject(proxy));
return JSObject::preventExtensions(cx, target);
}
static bool
GetFundamentalTrap(JSContext *cx, HandleObject handler, HandlePropertyName name,
MutableHandleValue fvalp)
@ -2489,6 +2504,14 @@ Proxy::iterate(JSContext *cx, HandleObject proxy, unsigned flags, MutableHandleV
return EnumeratedIdVectorToIterator(cx, proxy, flags, props, vp);
}
bool
Proxy::preventExtensions(JSContext *cx, HandleObject proxy)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
return handler->preventExtensions(cx, proxy);
}
bool
Proxy::isExtensible(JSObject *proxy)
{

View File

@ -104,6 +104,7 @@ class JS_FRIEND_API(BaseProxyHandler) {
bool *bp);
/* ES5 Harmony fundamental proxy traps. */
virtual bool preventExtensions(JSContext *cx, HandleObject proxy);
virtual bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
PropertyDescriptor *desc, unsigned flags) = 0;
virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy,
@ -159,6 +160,7 @@ public:
explicit DirectProxyHandler(void *family);
/* ES5 Harmony fundamental proxy traps. */
virtual bool preventExtensions(JSContext *cx, HandleObject proxy) MOZ_OVERRIDE;
virtual bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
PropertyDescriptor *desc, unsigned flags) MOZ_OVERRIDE;
virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy,
@ -209,6 +211,7 @@ public:
class Proxy {
public:
/* ES5 Harmony fundamental proxy traps. */
static bool preventExtensions(JSContext *cx, HandleObject proxy);
static bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
PropertyDescriptor *desc, unsigned flags);
static bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, unsigned flags, HandleId id,

View File

@ -636,6 +636,15 @@ SecurityWrapper<Base>::isExtensible(JSObject *wrapper)
return true;
}
template <class Base>
bool
SecurityWrapper<Base>::preventExtensions(JSContext *cx, HandleObject wrapper)
{
// See above.
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNWRAP_DENIED);
return false;
}
template <class Base>
bool
SecurityWrapper<Base>::enter(JSContext *cx, HandleObject wrapper, HandleId id,
@ -646,8 +655,8 @@ SecurityWrapper<Base>::enter(JSContext *cx, HandleObject wrapper, HandleId id,
return false;
}
template <class Base>
bool
template <class Base>
bool
SecurityWrapper<Base>::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
CallArgs args)
{

View File

@ -144,6 +144,7 @@ class JS_FRIEND_API(SecurityWrapper) : public Base
SecurityWrapper(unsigned flags);
virtual bool isExtensible(JSObject *wrapper) MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, HandleObject wrapper) MOZ_OVERRIDE;
virtual bool enter(JSContext *cx, HandleObject wrapper, HandleId id, Wrapper::Action act,
bool *bp) MOZ_OVERRIDE;
virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,

View File

@ -93,7 +93,6 @@ js::ObjectImpl::isExtensible() const
return !lastProperty()->hasObjectFlag(BaseShape::NOT_EXTENSIBLE);
}
inline uint32_t
js::ObjectImpl::getDenseInitializedLength()
{

View File

@ -1112,6 +1112,8 @@ class ObjectImpl : public gc::Cell
inline bool isExtensible() const;
// Attempt to change the [[Extensible]] bit on |obj| to false. Callers
// must ensure that |obj| is currently extensible before calling this!
static bool
preventExtensions(JSContext *cx, Handle<ObjectImpl*> obj);

View File

@ -1031,7 +1031,14 @@ Shape::setObjectParent(JSContext *cx, JSObject *parent, TaggedProto proto, Shape
/* static */ bool
js::ObjectImpl::preventExtensions(JSContext *cx, Handle<ObjectImpl*> obj)
{
JS_ASSERT(obj->isExtensible());
MOZ_ASSERT(obj->isExtensible(),
"Callers must ensure |obj| is extensible before calling "
"preventExtensions");
if (obj->isProxy()) {
RootedObject object(cx, obj->asObjectPtr());
return js::Proxy::preventExtensions(cx, object);
}
RootedObject self(cx, obj->asObjectPtr());

View File

@ -1428,6 +1428,15 @@ XrayWrapper<Base, Traits>::isExtensible(JSObject *wrapper)
return true;
}
template <typename Base, typename Traits>
bool
XrayWrapper<Base, Traits>::preventExtensions(JSContext *cx, JS::Handle<JSObject*> wrapper)
{
// See above.
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CHANGE_EXTENSIBILITY);
return false;
}
template <typename Base, typename Traits>
bool
XrayWrapper<Base, Traits>::getPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> wrapper,

View File

@ -67,6 +67,7 @@ class XrayWrapper : public Base {
/* Fundamental proxy traps. */
virtual bool isExtensible(JSObject *wrapper) MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> wrapper) MOZ_OVERRIDE;
virtual bool getPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
js::PropertyDescriptor *desc, unsigned flags);
virtual bool getOwnPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,