Bug 1050340 - Handle boxed values with a new proxy trap. r=luke

This commit is contained in:
Bobby Holley 2014-08-18 14:18:39 -07:00
parent bea169fd75
commit 93348157b7
7 changed files with 80 additions and 7 deletions

View File

@ -535,6 +535,10 @@ ObjectClassIs(JSObject &obj, ESClassValue classValue, JSContext *cx);
inline bool
IsObjectWithClass(const JS::Value &v, ESClassValue classValue, JSContext *cx);
/* Fills |vp| with the unboxed value for boxed types, or undefined otherwise. */
inline bool
Unbox(JSContext *cx, JS::HandleObject obj, JS::MutableHandleValue vp);
} /* namespace js */
#endif /* js_Class_h */

View File

@ -1046,6 +1046,24 @@ IsObjectWithClass(const Value &v, ESClassValue classValue, JSContext *cx)
return ObjectClassIs(obj, classValue, cx);
}
inline bool
Unbox(JSContext *cx, HandleObject obj, MutableHandleValue vp)
{
if (MOZ_UNLIKELY(obj->is<ProxyObject>()))
return Proxy::boxedValue_unbox(cx, obj, vp);
if (obj->is<BooleanObject>())
vp.setBoolean(obj->as<BooleanObject>().unbox());
else if (obj->is<NumberObject>())
vp.setNumber(obj->as<NumberObject>().unbox());
else if (obj->is<StringObject>())
vp.setString(obj->as<StringObject>().unbox());
else
vp.setUndefined();
return true;
}
static MOZ_ALWAYS_INLINE bool
NewObjectMetadata(ExclusiveContext *cxArg, JSObject **pmetadata)
{

View File

@ -329,6 +329,13 @@ BaseProxyHandler::regexp_toShared(JSContext *cx, HandleObject proxy,
MOZ_CRASH("This should have been a wrapped regexp");
}
bool
BaseProxyHandler::boxedValue_unbox(JSContext *cx, HandleObject proxy, MutableHandleValue vp) const
{
vp.setUndefined();
return true;
}
bool
BaseProxyHandler::defaultValue(JSContext *cx, HandleObject proxy, JSType hint,
MutableHandleValue vp) const
@ -558,6 +565,13 @@ DirectProxyHandler::regexp_toShared(JSContext *cx, HandleObject proxy,
return RegExpToShared(cx, target, g);
}
bool
DirectProxyHandler::boxedValue_unbox(JSContext *cx, HandleObject proxy, MutableHandleValue vp) const
{
RootedObject target(cx, proxy->as<ProxyObject>().target());
return Unbox(cx, target, vp);
}
JSObject *
DirectProxyHandler::weakmapKeyDelegate(JSObject *proxy) const
{
@ -2609,6 +2623,13 @@ Proxy::regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g)
return proxy->as<ProxyObject>().handler()->regexp_toShared(cx, proxy, g);
}
bool
Proxy::boxedValue_unbox(JSContext *cx, HandleObject proxy, MutableHandleValue vp)
{
JS_CHECK_RECURSION(cx, return false);
return proxy->as<ProxyObject>().handler()->boxedValue_unbox(cx, proxy, vp);
}
bool
Proxy::defaultValue(JSContext *cx, HandleObject proxy, JSType hint, MutableHandleValue vp)
{

View File

@ -206,6 +206,7 @@ class JS_FRIEND_API(BaseProxyHandler)
virtual const char *className(JSContext *cx, HandleObject proxy) const;
virtual JSString *fun_toString(JSContext *cx, HandleObject proxy, unsigned indent) const;
virtual bool regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g) const;
virtual bool boxedValue_unbox(JSContext *cx, HandleObject proxy, MutableHandleValue vp) const;
virtual bool defaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp) const;
virtual void finalize(JSFreeOp *fop, JSObject *proxy) const;
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const;
@ -289,6 +290,7 @@ class JS_PUBLIC_API(DirectProxyHandler) : public BaseProxyHandler
unsigned indent) const MOZ_OVERRIDE;
virtual bool regexp_toShared(JSContext *cx, HandleObject proxy,
RegExpGuard *g) const MOZ_OVERRIDE;
virtual bool boxedValue_unbox(JSContext *cx, HandleObject proxy, MutableHandleValue vp) const;
virtual JSObject *weakmapKeyDelegate(JSObject *proxy) const MOZ_OVERRIDE;
};
@ -338,6 +340,7 @@ class Proxy
static const char *className(JSContext *cx, HandleObject proxy);
static JSString *fun_toString(JSContext *cx, HandleObject proxy, unsigned indent);
static bool regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g);
static bool boxedValue_unbox(JSContext *cx, HandleObject proxy, MutableHandleValue vp);
static bool defaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp);
static bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop);
static bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto, bool *bp);

View File

@ -569,6 +569,15 @@ CrossCompartmentWrapper::regexp_toShared(JSContext *cx, HandleObject wrapper, Re
return cx->compartment()->regExps.get(cx, re->getSource(), re->getFlags(), g);
}
bool
CrossCompartmentWrapper::boxedValue_unbox(JSContext *cx, HandleObject wrapper, MutableHandleValue vp) const
{
PIERCE(cx, wrapper,
NOTHING,
Wrapper::boxedValue_unbox(cx, wrapper, vp),
cx->compartment()->wrap(cx, vp));
}
bool
CrossCompartmentWrapper::defaultValue(JSContext *cx, HandleObject wrapper, JSType hint,
MutableHandleValue vp) const
@ -689,6 +698,14 @@ SecurityWrapper<Base>::regexp_toShared(JSContext *cx, HandleObject obj, RegExpGu
return Base::regexp_toShared(cx, obj, g);
}
template <class Base>
bool
SecurityWrapper<Base>::boxedValue_unbox(JSContext *cx, HandleObject obj, MutableHandleValue vp) const
{
vp.setUndefined();
return true;
}
template <class Base>
bool
SecurityWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper,

View File

@ -144,6 +144,7 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
virtual JSString *fun_toString(JSContext *cx, HandleObject wrapper,
unsigned indent) const MOZ_OVERRIDE;
virtual bool regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g) const MOZ_OVERRIDE;
virtual bool boxedValue_unbox(JSContext *cx, HandleObject proxy, MutableHandleValue vp) const MOZ_OVERRIDE;
virtual bool defaultValue(JSContext *cx, HandleObject wrapper, JSType hint,
MutableHandleValue vp) const MOZ_OVERRIDE;
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
@ -181,6 +182,7 @@ class JS_FRIEND_API(SecurityWrapper) : public Base
virtual bool objectClassIs(HandleObject obj, ESClassValue classValue,
JSContext *cx) const MOZ_OVERRIDE;
virtual bool regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g) const MOZ_OVERRIDE;
virtual bool boxedValue_unbox(JSContext *cx, HandleObject proxy, MutableHandleValue vp) const MOZ_OVERRIDE;
virtual bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;

View File

@ -1028,13 +1028,21 @@ JSStructuredCloneWriter::startWrite(HandleValue v)
return writeArrayBuffer(obj);
} else if (obj->is<JSObject>() || obj->is<ArrayObject>()) {
return traverseObject(obj);
} else if (obj->is<BooleanObject>()) {
return out.writePair(SCTAG_BOOLEAN_OBJECT, obj->as<BooleanObject>().unbox());
} else if (obj->is<NumberObject>()) {
return out.writePair(SCTAG_NUMBER_OBJECT, 0) &&
out.writeDouble(obj->as<NumberObject>().unbox());
} else if (obj->is<StringObject>()) {
return writeString(SCTAG_STRING_OBJECT, obj->as<StringObject>().unbox());
} else if (ObjectClassIs(obj, ESClass_Boolean, context())) {
RootedValue unboxed(context());
if (!Unbox(context(), obj, &unboxed))
return false;
return out.writePair(SCTAG_BOOLEAN_OBJECT, unboxed.toBoolean());
} else if (ObjectClassIs(obj, ESClass_Number, context())) {
RootedValue unboxed(context());
if (!Unbox(context(), obj, &unboxed))
return false;
return out.writePair(SCTAG_NUMBER_OBJECT, 0) && out.writeDouble(unboxed.toNumber());
} else if (ObjectClassIs(obj, ESClass_String, context())) {
RootedValue unboxed(context());
if (!Unbox(context(), obj, &unboxed))
return false;
return writeString(SCTAG_STRING_OBJECT, unboxed.toString());
} else if (obj->is<MapObject>()) {
return traverseMap(obj);
} else if (obj->is<SetObject>()) {