mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 697343 - Introduce a slice hook to allow optimizing Array.prototype.slice for Proxies etc. r=jandem,bz
This commit is contained in:
parent
aa96007c5a
commit
ac84baff89
@ -169,7 +169,11 @@ function expandPermissions(aPerms) {
|
||||
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;
|
||||
|
@ -380,6 +380,10 @@ typedef bool
|
||||
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
|
||||
@ -468,6 +472,7 @@ struct ObjectOps
|
||||
DeleteSpecialOp deleteSpecial;
|
||||
WatchOp watch;
|
||||
UnwatchOp unwatch;
|
||||
SliceOp slice; // Optimized slice, can be null.
|
||||
|
||||
JSNewEnumerateOp enumerate;
|
||||
ObjectOp thisObject;
|
||||
|
@ -2498,6 +2498,7 @@ const Class TypedObject::class_ = {
|
||||
TypedDatum::obj_deleteElement,
|
||||
TypedDatum::obj_deleteSpecial,
|
||||
nullptr, nullptr, // watch/unwatch
|
||||
nullptr, /* slice */
|
||||
TypedDatum::obj_enumerate,
|
||||
nullptr, /* thisObject */
|
||||
}
|
||||
@ -2664,6 +2665,7 @@ const Class TypedHandle::class_ = {
|
||||
TypedDatum::obj_deleteElement,
|
||||
TypedDatum::obj_deleteSpecial,
|
||||
nullptr, nullptr, // watch/unwatch
|
||||
nullptr, // slice
|
||||
TypedDatum::obj_enumerate,
|
||||
nullptr, /* thisObject */
|
||||
}
|
||||
|
@ -2673,20 +2673,18 @@ js::array_concat(JSContext *cx, unsigned argc, Value *vp)
|
||||
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))
|
||||
@ -2734,13 +2732,23 @@ array_slice(JSContext *cx, unsigned argc, Value *vp)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -364,6 +364,34 @@ 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)
|
||||
@ -2720,6 +2748,18 @@ Proxy::unwatch(JSContext *cx, JS::HandleObject proxy, JS::HandleId id)
|
||||
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)
|
||||
{
|
||||
@ -3013,17 +3053,24 @@ proxy_Construct(JSContext *cx, unsigned argc, Value *vp)
|
||||
}
|
||||
|
||||
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 */ \
|
||||
@ -3076,6 +3123,7 @@ proxy_Unwatch(JSContext *cx, JS::HandleObject obj, JS::HandleId id)
|
||||
proxy_DeleteElement, \
|
||||
proxy_DeleteSpecial, \
|
||||
proxy_Watch, proxy_Unwatch, \
|
||||
proxy_Slice, \
|
||||
nullptr, /* enumerate */ \
|
||||
nullptr, /* thisObject */ \
|
||||
} \
|
||||
@ -3133,6 +3181,7 @@ const Class js::OuterWindowProxyObject::class_ = {
|
||||
proxy_DeleteElement,
|
||||
proxy_DeleteSpecial,
|
||||
proxy_Watch, proxy_Unwatch,
|
||||
proxy_Slice,
|
||||
nullptr, /* enumerate */
|
||||
nullptr, /* thisObject */
|
||||
}
|
||||
|
@ -174,6 +174,9 @@ class JS_FRIEND_API(BaseProxyHandler)
|
||||
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; }
|
||||
@ -292,9 +295,11 @@ class Proxy
|
||||
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,
|
||||
|
@ -566,7 +566,8 @@ const Class WithObject::class_ = {
|
||||
with_DeleteProperty,
|
||||
with_DeleteElement,
|
||||
with_DeleteSpecial,
|
||||
nullptr, nullptr, /* watch/unwatch */
|
||||
nullptr, nullptr, /* watch/unwatch */
|
||||
nullptr, /* slice */
|
||||
with_Enumerate,
|
||||
with_ThisObject,
|
||||
}
|
||||
|
@ -3460,8 +3460,9 @@ const Class ArrayBufferObject::class_ = {
|
||||
ArrayBufferObject::obj_deleteElement,
|
||||
ArrayBufferObject::obj_deleteSpecial,
|
||||
nullptr, nullptr, /* watch/unwatch */
|
||||
nullptr, /* slice */
|
||||
ArrayBufferObject::obj_enumerate,
|
||||
nullptr, /* thisObject */
|
||||
nullptr, /* thisObject */
|
||||
}
|
||||
};
|
||||
|
||||
@ -3622,8 +3623,9 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double)
|
||||
_typedArray##Object::obj_deleteElement, \
|
||||
_typedArray##Object::obj_deleteSpecial, \
|
||||
nullptr, nullptr, /* watch/unwatch */ \
|
||||
nullptr, /* slice */ \
|
||||
_typedArray##Object::obj_enumerate, \
|
||||
nullptr, /* thisObject */ \
|
||||
nullptr, /* thisObject */ \
|
||||
} \
|
||||
}
|
||||
|
||||
|
@ -731,6 +731,7 @@ const XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass = {
|
||||
nullptr, // deleteElement
|
||||
nullptr, // deleteSpecial
|
||||
nullptr, nullptr, // watch/unwatch
|
||||
nullptr, // slice
|
||||
XPC_WN_JSOp_Enumerate,
|
||||
XPC_WN_JSOp_ThisObject,
|
||||
}
|
||||
|
@ -992,6 +992,7 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS::HandleObject obj);
|
||||
nullptr, /* deleteElement */ \
|
||||
nullptr, /* deleteSpecial */ \
|
||||
nullptr, nullptr, /* watch/unwatch */ \
|
||||
nullptr, /* slice */ \
|
||||
XPC_WN_JSOp_Enumerate, \
|
||||
XPC_WN_JSOp_ThisObject, \
|
||||
}
|
||||
@ -1020,6 +1021,7 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS::HandleObject obj);
|
||||
nullptr, /* deleteElement */ \
|
||||
nullptr, /* deleteSpecial */ \
|
||||
nullptr, nullptr, /* watch/unwatch */ \
|
||||
nullptr, /* slice */ \
|
||||
XPC_WN_JSOp_Enumerate, \
|
||||
XPC_WN_JSOp_ThisObject, \
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user