diff -r d0a8da1b9fce js/src/jsproxy.cpp --- a/js/src/jsproxy.cpp Wed Aug 08 23:09:22 2012 +0200 +++ b/js/src/jsproxy.cpp Wed Aug 08 23:10:00 2012 +0200 @@ -607,27 +607,19 @@ DirectProxyHandler::iterate(JSContext *c if (!GetIterator(cx, target, flags, &value)) return false; *vp = value; return true; } static bool -GetTrap(JSContext *cx, HandleObject handler, HandlePropertyName name, MutableHandleValue fvalp) -{ - JS_CHECK_RECURSION(cx, return false); - - return handler->getProperty(cx, name, fvalp); -} - -static bool GetFundamentalTrap(JSContext *cx, HandleObject handler, HandlePropertyName name, MutableHandleValue fvalp) { - if (!GetTrap(cx, handler, name, fvalp)) + if (!handler->getProperty(cx, name, fvalp)) return false; if (!js_IsCallable(fvalp)) { JSAutoByteString bytes; if (js_AtomToPrintableString(cx, name, &bytes)) JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_FUNCTION, bytes.ptr()); return false; } @@ -640,17 +632,17 @@ GetDerivedTrap(JSContext *cx, HandleObje { JS_ASSERT(name == ATOM(has) || name == ATOM(hasOwn) || name == ATOM(get) || name == ATOM(set) || name == ATOM(keys) || name == ATOM(iterate)); - return GetTrap(cx, handler, name, fvalp); + return handler->getProperty(cx, name, fvalp); } static bool Trap(JSContext *cx, HandleObject handler, HandleValue fval, unsigned argc, Value* argv, Value *rval) { return Invoke(cx, ObjectValue(*handler), fval, argc, argv, rval); } @@ -1128,16 +1120,198 @@ NormalizePropertyDescriptor(JSContext *c /* Aux.4 NormalizeAndCompletePropertyDescriptor(Attributes) */ static inline bool NormalizeAndCompletePropertyDescriptor(JSContext *cx, MutableHandleValue vp) { return NormalizePropertyDescriptor(cx, vp, true); } +static inline bool +IsDataDescriptor(const PropertyDescriptor &desc) +{ + return !desc.obj && !(desc.attrs & (JSPROP_GETTER | JSPROP_SETTER)); +} + +static inline bool +IsAccessorDescriptor(const PropertyDescriptor &desc) +{ + return !desc.obj && desc.attrs & (JSPROP_GETTER | JSPROP_SETTER); +} + +/* Aux.5 ValidateProperty(O, P, Desc) */ +static bool +ValidateProperty(JSContext *cx, HandleObject obj, HandleId id, PropDesc *desc, bool *bp) +{ + /* Aux.5 step 1 */ + AutoPropertyDescriptorRooter current(cx); + if (!GetOwnPropertyDescriptor(cx, obj, id, 0, ¤t)) + return false; + + /* Aux.5 step 2 */ + bool extensible = obj->isExtensible(); + + /* Aux.5 step 3 */ + if (!current.obj && !extensible) { + *bp = false; + return true; + } + + /* Aux.5 step 4 */ + if (!current.obj && extensible) { + *bp = true; + return true; + } + + /* Aux.5 step 5 */ + if (!desc->hasValue() && !desc->hasWritable() && !desc->hasGet() && !desc->hasSet() && + !desc->hasEnumerable() && !desc->hasConfigurable()) { + *bp = true; + return true; + } + + /* Aux.5 step 6 */ + if ((!desc->hasWritable() || desc->writable() == !(current.attrs & JSPROP_READONLY)) && + (!desc->hasGet() || desc->getter() == current.getter) && + (!desc->hasSet() || desc->setter() == current.setter) && + (!desc->hasEnumerable() || desc->enumerable() == current.attrs & JSPROP_ENUMERATE) && + (!desc->hasConfigurable() || desc->configurable() == !(current.attrs & JSPROP_PERMANENT))) { + if (!desc->hasValue()) { + *bp = true; + return true; + } + bool same = false; + if (!SameValue(cx, desc->value(), current.value, &same)) + return false; + if (same) { + *bp = true; + return true; + } + } + + /* Aux.5 step 7 */ + if (current.attrs & JSPROP_PERMANENT) { + if (desc->hasConfigurable() && desc->configurable()) { + *bp = false; + return true; + } + + if (desc->hasEnumerable() && + desc->enumerable() != (current.attrs & JSPROP_ENUMERATE)) { + *bp = false; + return true; + } + } + + /* Aux.5 step 8 */ + if (desc->isGenericDescriptor()) { + *bp = true; + return true; + } + + /* Aux.5 step 9 */ + if (IsDataDescriptor(current) != desc->isDataDescriptor()) { + if (current.attrs & JSPROP_PERMANENT) { + *bp = false; + return true; + } + + *bp = true; + return true; + } + + /* Aux.5 step 10 */ + if (IsDataDescriptor(current) && desc->isDataDescriptor()) { + if (current.attrs & JSPROP_PERMANENT) { + if (current.attrs & JSPROP_READONLY && desc->hasWritable() && desc->writable()) { + *bp = false; + return true; + } + + if (current.attrs & JSPROP_READONLY) { + if (desc->hasValue()) { + bool same; + if (!SameValue(cx, desc->value(), current.value, &same)) + return false; + if (!same) { + *bp = false; + return true; + } + } + } + } + + *bp = true; + return true; + } + + /* Aux.5 step 11 */ + if (IsAccessorDescriptor(current) && desc->isAccessorDescriptor()) { + if (current.attrs & JSPROP_PERMANENT) { + if (desc->hasSet() && desc->setter() != current.setter) { + *bp = false; + return true; + } + if (desc->hasGet() && desc->getter() != current.getter) { + *bp = false; + return true; + } + } + } + + /* Aux.5 step 12 */ + *bp = true; + return true; +} + +/* Aux.6 IsSealed(O, P) */ +static bool +IsSealed(JSContext* cx, HandleObject obj, HandleId id, bool *bp) +{ + /* Aux.6 step 1 */ + AutoPropertyDescriptorRooter desc(cx); + if (!GetOwnPropertyDescriptor(cx, obj, id, 0, &desc)) + return false; + + /* Aux.6 step 2 */ + if (!desc.obj) { + *bp = false; + return true; + } + + /* Aux.6 step 3 */ + *bp = desc.attrs & JSPROP_PERMANENT; + return true; +} + +/* Aux.7 GetTrap(H, P) */ +static bool +GetTrap(JSContext *cx, HandleObject handler, HandlePropertyName name, MutableHandleValue rval) +{ + /* Aux.7 step 1 */ + *rval.address() = UndefinedValue(); + if (handler && !handler->getProperty(cx, name, rval)) + return false; + + /* Aux.7 step 2 */ + if (rval.isUndefined()) + return true; + + /* Aux.7 step 3 */ + if (!js_IsCallable(rval)) { + JSAutoByteString bytes; + if (js_AtomToPrintableString(cx, name, &bytes)) + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_FUNCTION, bytes.ptr()); + return false; + } + + /* Aux.7 step 4 */ + return true; +} + ScriptedDirectProxyHandler::ScriptedDirectProxyHandler() : DirectProxyHandler(&sScriptedDirectProxyHandlerFamily) { } ScriptedDirectProxyHandler::~ScriptedDirectProxyHandler() { }