author | Tom Schuster <evilpies@gmail.com> |
Thu, 05 Dec 2013 20:07:24 +0100 | |
changeset 159635 | aa573b104bdfe1bf994d14dd0bb6de2465791953 |
parent 159634 | e0803c4ddc9020cc46128326b8a2b82c96d1e790 |
child 159636 | 0fbdff3a10e38819be92320e95e8a98c93186662 |
push id | 25808 |
push user | cbook@mozilla.com |
push date | Tue, 10 Dec 2013 12:03:31 +0000 |
treeherder | mozilla-central@7fb91a422c5e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem, bz |
bugs | 697343 |
milestone | 29.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/permission/tests/file_framework.js +++ b/dom/permission/tests/file_framework.js @@ -164,17 +164,21 @@ function addPermissions(aPerms, aDoc, aC SpecialPowers.pushPermissions(permList, aCallback); } function expandPermissions(aPerms) { var perms = []; aPerms.forEach(function(el) { var access = permTable[el].access ? "readwrite" : null; var expanded = SpecialPowers.unwrap(expand(el, access)); - perms = perms.concat(expanded.slice(0)); + // COW arrays don't behave array-like enough, to allow + // using expanded.slice(0) here. + for (let i = 0; i < expanded.length; i++) { + perms.push(expanded[i]); + } }); return perms; } function msgHandler(evt) { var data = evt.data; var test = pendingTests[data.id];
--- a/js/public/Class.h +++ b/js/public/Class.h @@ -375,16 +375,20 @@ typedef bool (* DeleteSpecialOp)(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid, bool *succeeded); typedef bool (* WatchOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable); typedef bool (* UnwatchOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id); +typedef bool +(* SliceOp)(JSContext *cx, JS::HandleObject obj, uint32_t begin, uint32_t end, + JS::HandleObject result); // result is actually preallocted. + typedef JSObject * (* ObjectOp)(JSContext *cx, JS::HandleObject obj); typedef void (* FinalizeOp)(FreeOp *fop, JSObject *obj); #define JS_CLASS_MEMBERS \ const char *name; \ uint32_t flags; \ @@ -463,16 +467,17 @@ struct ObjectOps StrictSpecialIdOp setSpecial; GenericAttributesOp getGenericAttributes; GenericAttributesOp setGenericAttributes; DeletePropertyOp deleteProperty; DeleteElementOp deleteElement; DeleteSpecialOp deleteSpecial; WatchOp watch; UnwatchOp unwatch; + SliceOp slice; // Optimized slice, can be null. JSNewEnumerateOp enumerate; ObjectOp thisObject; }; #define JS_NULL_OBJECT_OPS \ {nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, \ nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, \
--- a/js/src/builtin/TypedObject.cpp +++ b/js/src/builtin/TypedObject.cpp @@ -2493,16 +2493,17 @@ const Class TypedObject::class_ = { TypedDatum::obj_setElement, TypedDatum::obj_setSpecial, TypedDatum::obj_getGenericAttributes, TypedDatum::obj_setGenericAttributes, TypedDatum::obj_deleteProperty, TypedDatum::obj_deleteElement, TypedDatum::obj_deleteSpecial, nullptr, nullptr, // watch/unwatch + nullptr, /* slice */ TypedDatum::obj_enumerate, nullptr, /* thisObject */ } }; /*static*/ TypedObject * TypedObject::createZeroed(JSContext *cx, HandleObject typeObj, @@ -2659,16 +2660,17 @@ const Class TypedHandle::class_ = { TypedDatum::obj_setElement, TypedDatum::obj_setSpecial, TypedDatum::obj_getGenericAttributes, TypedDatum::obj_setGenericAttributes, TypedDatum::obj_deleteProperty, TypedDatum::obj_deleteElement, TypedDatum::obj_deleteSpecial, nullptr, nullptr, // watch/unwatch + nullptr, // slice TypedDatum::obj_enumerate, nullptr, /* thisObject */ } }; const JSFunctionSpec TypedHandle::handleStaticMethods[] = { {"move", {nullptr, nullptr}, 3, 0, "HandleMove"}, {"get", {nullptr, nullptr}, 1, 0, "HandleGet"},
--- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -2668,30 +2668,28 @@ js::array_concat(JSContext *cx, unsigned } return SetLengthProperty(cx, narr, length); } static bool array_slice(JSContext *cx, unsigned argc, Value *vp) { - uint32_t length, begin, end, slot; - bool hole; - CallArgs args = CallArgsFromVp(argc, vp); RootedObject obj(cx, ToObject(cx, args.thisv())); if (!obj) return false; + uint32_t length; if (!GetLengthProperty(cx, obj, &length)) return false; - begin = 0; - end = length; - + + uint32_t begin = 0; + uint32_t end = length; if (args.length() > 0) { double d; if (!ToInteger(cx, args[0], &d)) return false; if (d < 0) { d += length; if (d < 0) d = 0; @@ -2729,23 +2727,33 @@ array_slice(JSContext *cx, unsigned argc uint32_t initLength = Min(numSourceElements, end - begin); narr->setDenseInitializedLength(initLength); narr->initDenseElements(0, &obj->getDenseElement(begin), initLength); } args.rval().setObject(*narr); return true; } + if (js::SliceOp op = obj->getOps()->slice) { + if (!op(cx, obj, begin, end, narr)) + return false; + + args.rval().setObject(*narr); + return true; + } + RootedValue value(cx); - for (slot = begin; slot < end; slot++) { + for (uint32_t slot = begin; slot < end; slot++) { + bool hole; if (!JS_CHECK_OPERATION_LIMIT(cx) || - !GetElement(cx, obj, slot, &hole, &value)) { + !GetElement(cx, obj, slot, &hole, &value)) + { return false; } - if (!hole && !SetArrayElement(cx, narr, slot - begin, value)) + if (!hole && !JSObject::defineElement(cx, narr, slot - begin, value)) return false; } args.rval().setObject(*narr); return true; } /* ES5 15.4.4.20. */
--- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -360,16 +360,44 @@ BaseProxyHandler::watch(JSContext *cx, H bool BaseProxyHandler::unwatch(JSContext *cx, HandleObject proxy, HandleId id) { return true; } bool +BaseProxyHandler::slice(JSContext *cx, HandleObject proxy, uint32_t begin, uint32_t end, + HandleObject result) +{ + assertEnteredPolicy(cx, proxy, JSID_VOID); + + RootedId id(cx); + RootedValue value(cx); + for (uint32_t index = begin; index < end; index++) { + if (!IndexToId(cx, index, id.address())) + return false; + + bool present; + if (!Proxy::has(cx, proxy, id, &present)) + return false; + + if (present) { + if (!Proxy::get(cx, proxy, proxy, id, &value)) + return false; + + if (!JSObject::defineElement(cx, result, index - begin, value)) + return false; + } + } + + return true; +} + +bool DirectProxyHandler::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id, MutableHandle<PropertyDescriptor> desc, unsigned flags) { assertEnteredPolicy(cx, proxy, id); JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype. RootedObject target(cx, proxy->as<ProxyObject>().target()); return JS_GetPropertyDescriptorById(cx, target, id, 0, desc); } @@ -2715,16 +2743,28 @@ Proxy::watch(JSContext *cx, JS::HandleOb /* static */ bool Proxy::unwatch(JSContext *cx, JS::HandleObject proxy, JS::HandleId id) { JS_CHECK_RECURSION(cx, return false); return proxy->as<ProxyObject>().handler()->unwatch(cx, proxy, id); } +/* static */ bool +Proxy::slice(JSContext *cx, HandleObject proxy, uint32_t begin, uint32_t end, + HandleObject result) +{ + JS_CHECK_RECURSION(cx, return false); + BaseProxyHandler *handler = proxy->as<ProxyObject>().handler(); + AutoEnterPolicy policy(cx, handler, proxy, JSID_VOIDHANDLE, BaseProxyHandler::GET, true); + if (!policy.allowed()) + return policy.returnValue(); + return handler->slice(cx, proxy, begin, end, result); +} + static JSObject * proxy_innerObject(JSContext *cx, HandleObject obj) { return obj->as<ProxyObject>().private_().toObjectOrNull(); } static bool proxy_LookupGeneric(JSContext *cx, HandleObject obj, HandleId id, @@ -3008,27 +3048,34 @@ proxy_Construct(JSContext *cx, unsigned { CallArgs args = CallArgsFromVp(argc, vp); RootedObject proxy(cx, &args.callee()); JS_ASSERT(proxy->is<ProxyObject>()); return Proxy::construct(cx, proxy, args); } static bool -proxy_Watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable) +proxy_Watch(JSContext *cx, HandleObject obj, HandleId id, HandleObject callable) { return Proxy::watch(cx, obj, id, callable); } static bool -proxy_Unwatch(JSContext *cx, JS::HandleObject obj, JS::HandleId id) +proxy_Unwatch(JSContext *cx, HandleObject obj, HandleId id) { return Proxy::unwatch(cx, obj, id); } +static bool +proxy_Slice(JSContext *cx, HandleObject proxy, uint32_t begin, uint32_t end, + HandleObject result) +{ + return Proxy::slice(cx, proxy, begin, end, result); +} + #define PROXY_CLASS_EXT \ { \ nullptr, /* outerObject */ \ nullptr, /* innerObject */ \ nullptr, /* iteratorObject */ \ false, /* isWrappedNative */ \ proxy_WeakmapKeyDelegate \ } @@ -3071,16 +3118,17 @@ proxy_Unwatch(JSContext *cx, JS::HandleO proxy_SetElement, \ proxy_SetSpecial, \ proxy_GetGenericAttributes, \ proxy_SetGenericAttributes, \ proxy_DeleteProperty, \ proxy_DeleteElement, \ proxy_DeleteSpecial, \ proxy_Watch, proxy_Unwatch, \ + proxy_Slice, \ nullptr, /* enumerate */ \ nullptr, /* thisObject */ \ } \ } const Class js::ProxyObject::uncallableClass_ = PROXY_CLASS(nullptr, nullptr); const Class js::ProxyObject::callableClass_ = PROXY_CLASS(proxy_Call, proxy_Construct); @@ -3128,16 +3176,17 @@ const Class js::OuterWindowProxyObject:: proxy_SetElement, proxy_SetSpecial, proxy_GetGenericAttributes, proxy_SetGenericAttributes, proxy_DeleteProperty, proxy_DeleteElement, proxy_DeleteSpecial, proxy_Watch, proxy_Unwatch, + proxy_Slice, nullptr, /* enumerate */ nullptr, /* thisObject */ } }; const Class* const js::OuterWindowProxyClassPtr = &OuterWindowProxyObject::class_; JS_FRIEND_API(JSObject *)
--- a/js/src/jsproxy.h +++ b/js/src/jsproxy.h @@ -169,16 +169,19 @@ class JS_FRIEND_API(BaseProxyHandler) virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop); // These two hooks must be overridden, or not overridden, in tandem -- no // overriding just one! virtual bool watch(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleObject callable); virtual bool unwatch(JSContext *cx, JS::HandleObject proxy, JS::HandleId id); + virtual bool slice(JSContext *cx, HandleObject proxy, uint32_t begin, uint32_t end, + HandleObject result); + /* See comment for weakmapKeyDelegateOp in js/Class.h. */ virtual JSObject *weakmapKeyDelegate(JSObject *proxy); virtual bool isScripted() { return false; } }; /* * DirectProxyHandler includes a notion of a target object. All traps are * reimplemented such that they forward their behavior to the target. This @@ -287,19 +290,21 @@ class Proxy static bool hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool *bp); static bool objectClassIs(HandleObject obj, ESClassValue classValue, JSContext *cx); 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 defaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp); static bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop); - static bool watch(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, - JS::HandleObject callable); - static bool unwatch(JSContext *cx, JS::HandleObject proxy, JS::HandleId id); + static bool watch(JSContext *cx, HandleObject proxy, HandleId id, HandleObject callable); + static bool unwatch(JSContext *cx, HandleObject proxy, HandleId id); + + static bool slice(JSContext *cx, HandleObject obj, uint32_t begin, uint32_t end, + HandleObject result); /* IC entry path for handling __noSuchMethod__ on access. */ static bool callProp(JSContext *cx, HandleObject proxy, HandleObject reveiver, HandleId id, MutableHandleValue vp); static JSObject * const LazyProto; };
--- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -561,17 +561,18 @@ const Class WithObject::class_ = { with_SetProperty, with_SetElement, with_SetSpecial, with_GetGenericAttributes, with_SetGenericAttributes, with_DeleteProperty, with_DeleteElement, with_DeleteSpecial, - nullptr, nullptr, /* watch/unwatch */ + nullptr, nullptr, /* watch/unwatch */ + nullptr, /* slice */ with_Enumerate, with_ThisObject, } }; /*****************************************************************************/ ClonedBlockObject *
--- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -3455,18 +3455,19 @@ const Class ArrayBufferObject::class_ = ArrayBufferObject::obj_setElement, ArrayBufferObject::obj_setSpecial, ArrayBufferObject::obj_getGenericAttributes, ArrayBufferObject::obj_setGenericAttributes, ArrayBufferObject::obj_deleteProperty, ArrayBufferObject::obj_deleteElement, ArrayBufferObject::obj_deleteSpecial, nullptr, nullptr, /* watch/unwatch */ + nullptr, /* slice */ ArrayBufferObject::obj_enumerate, - nullptr, /* thisObject */ + nullptr, /* thisObject */ } }; const JSFunctionSpec ArrayBufferObject::jsfuncs[] = { JS_FN("slice", ArrayBufferObject::fun_slice, 2, JSFUN_GENERIC_NATIVE), JS_FS_END }; @@ -3617,18 +3618,19 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Flo _typedArray##Object::obj_setElement, \ _typedArray##Object::obj_setSpecial, \ _typedArray##Object::obj_getGenericAttributes, \ _typedArray##Object::obj_setGenericAttributes, \ _typedArray##Object::obj_deleteProperty, \ _typedArray##Object::obj_deleteElement, \ _typedArray##Object::obj_deleteSpecial, \ nullptr, nullptr, /* watch/unwatch */ \ + nullptr, /* slice */ \ _typedArray##Object::obj_enumerate, \ - nullptr, /* thisObject */ \ + nullptr, /* thisObject */ \ } \ } template<class ArrayType> static inline JSObject * InitTypedArrayClass(JSContext *cx) { Rooted<GlobalObject*> global(cx, cx->compartment()->maybeGlobal());
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp +++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp @@ -726,16 +726,17 @@ const XPCWrappedNativeJSClass XPC_WN_NoH nullptr, // setElement nullptr, // setSpecial nullptr, // getGenericAttributes nullptr, // setGenericAttributes nullptr, // deleteProperty nullptr, // deleteElement nullptr, // deleteSpecial nullptr, nullptr, // watch/unwatch + nullptr, // slice XPC_WN_JSOp_Enumerate, XPC_WN_JSOp_ThisObject, } }, 0 // interfacesBitmap };
--- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -987,16 +987,17 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS nullptr, /* setElement */ \ nullptr, /* setSpecial */ \ nullptr, /* getGenericAttributes */ \ nullptr, /* setGenericAttributes */ \ nullptr, /* deleteProperty */ \ nullptr, /* deleteElement */ \ nullptr, /* deleteSpecial */ \ nullptr, nullptr, /* watch/unwatch */ \ + nullptr, /* slice */ \ XPC_WN_JSOp_Enumerate, \ XPC_WN_JSOp_ThisObject, \ } #define XPC_WN_NoCall_ObjectOps \ { \ nullptr, /* lookupGeneric */ \ nullptr, /* lookupProperty */ \ @@ -1015,16 +1016,17 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS nullptr, /* setElement */ \ nullptr, /* setSpecial */ \ nullptr, /* getGenericAttributes */ \ nullptr, /* setGenericAttributes */ \ nullptr, /* deleteProperty */ \ nullptr, /* deleteElement */ \ nullptr, /* deleteSpecial */ \ nullptr, nullptr, /* watch/unwatch */ \ + nullptr, /* slice */ \ XPC_WN_JSOp_Enumerate, \ XPC_WN_JSOp_ThisObject, \ } // Maybe this macro should check for class->enumerate == // XPC_WN_Shared_Proto_Enumerate or something rather than checking for // 4 classes? static inline bool IS_PROTO_CLASS(const js::Class *clazz)