зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changesets 22770b30545b, 0809370fabdb, 4ef4764c1b55, and bfe768b87464 (bug 697343) due to Gaia UI test bustage.
CLOSED TREE
This commit is contained in:
Родитель
b62e9cf287
Коммит
5c07e15985
|
@ -7572,13 +7572,8 @@ class CGProxySpecialOperation(CGPerSignatureCall):
|
|||
"""
|
||||
Base class for classes for calling an indexed or named special operation
|
||||
(don't use this directly, use the derived classes below).
|
||||
|
||||
If checkFound is False, will just assert that the prop is found instead of
|
||||
checking that it is before wrapping the value.
|
||||
"""
|
||||
def __init__(self, descriptor, operation, checkFound=True):
|
||||
self.checkFound = checkFound;
|
||||
|
||||
def __init__(self, descriptor, operation):
|
||||
nativeName = MakeNativeName(descriptor.binaryNames.get(operation, operation))
|
||||
operation = descriptor.operations[operation]
|
||||
assert len(operation.signatures()) == 1
|
||||
|
@ -7624,26 +7619,15 @@ class CGProxySpecialOperation(CGPerSignatureCall):
|
|||
return ""
|
||||
|
||||
wrap = CGGeneric(wrapForType(self.returnType, self.descriptor, self.templateValues))
|
||||
if self.checkFound:
|
||||
wrap = CGIfWrapper(wrap, "found")
|
||||
else:
|
||||
wrap = CGList([CGGeneric("MOZ_ASSERT(found);"), wrap], "\n")
|
||||
wrap = CGIfWrapper(wrap, "found")
|
||||
return "\n" + wrap.define()
|
||||
|
||||
class CGProxyIndexedOperation(CGProxySpecialOperation):
|
||||
"""
|
||||
Class to generate a call to an indexed operation.
|
||||
|
||||
If doUnwrap is False, the caller is responsible for making sure a variable
|
||||
named 'self' holds the C++ object somewhere where the code we generate
|
||||
will see it.
|
||||
|
||||
If checkFound is False, will just assert that the prop is found instead of
|
||||
checking that it is before wrapping the value.
|
||||
"""
|
||||
def __init__(self, descriptor, name, doUnwrap=True, checkFound=True):
|
||||
self.doUnwrap = doUnwrap
|
||||
CGProxySpecialOperation.__init__(self, descriptor, name, checkFound)
|
||||
def __init__(self, descriptor, name):
|
||||
CGProxySpecialOperation.__init__(self, descriptor, name)
|
||||
def define(self):
|
||||
# Our first argument is the id we're getting.
|
||||
argName = self.arguments[0].identifier.name
|
||||
|
@ -7652,30 +7636,18 @@ class CGProxyIndexedOperation(CGProxySpecialOperation):
|
|||
setIndex = ""
|
||||
else:
|
||||
setIndex = "uint32_t %s = index;\n" % argName
|
||||
if self.doUnwrap:
|
||||
unwrap = "%s* self = UnwrapProxy(proxy);\n"
|
||||
else:
|
||||
unwrap = ""
|
||||
return (setIndex + unwrap +
|
||||
return (setIndex +
|
||||
"%s* self = UnwrapProxy(proxy);\n" +
|
||||
CGProxySpecialOperation.define(self))
|
||||
|
||||
class CGProxyIndexedGetter(CGProxyIndexedOperation):
|
||||
"""
|
||||
Class to generate a call to an indexed getter. If templateValues is not None
|
||||
the returned value will be wrapped with wrapForType using templateValues.
|
||||
|
||||
If doUnwrap is False, the caller is responsible for making sure a variable
|
||||
named 'self' holds the C++ object somewhere where the code we generate
|
||||
will see it.
|
||||
|
||||
If checkFound is False, will just assert that the prop is found instead of
|
||||
checking that it is before wrapping the value.
|
||||
"""
|
||||
def __init__(self, descriptor, templateValues=None, doUnwrap=True,
|
||||
checkFound=True):
|
||||
def __init__(self, descriptor, templateValues=None):
|
||||
self.templateValues = templateValues
|
||||
CGProxyIndexedOperation.__init__(self, descriptor, 'IndexedGetter',
|
||||
doUnwrap, checkFound)
|
||||
CGProxyIndexedOperation.__init__(self, descriptor, 'IndexedGetter')
|
||||
|
||||
class CGProxyIndexedPresenceChecker(CGProxyIndexedGetter):
|
||||
"""
|
||||
|
@ -8312,55 +8284,65 @@ class CGDOMJSProxyHandler_finalize(ClassMethod):
|
|||
return ("%s self = UnwrapProxy(proxy);\n\n" % (self.descriptor.nativeType + "*") +
|
||||
finalizeHook(self.descriptor, FINALIZE_HOOK_NAME, self.args[0].name).define())
|
||||
|
||||
class CGDOMJSProxyHandler_slice(ClassMethod):
|
||||
class CGDOMJSProxyHandler_getElementIfPresent(ClassMethod):
|
||||
def __init__(self, descriptor):
|
||||
assert descriptor.supportsIndexedProperties()
|
||||
|
||||
args = [Argument('JSContext*', 'cx'),
|
||||
Argument('JS::Handle<JSObject*>', 'proxy'),
|
||||
Argument('uint32_t', 'begin'),
|
||||
Argument('uint32_t', 'end'),
|
||||
Argument('JS::Handle<JSObject*>', 'array')]
|
||||
ClassMethod.__init__(self, "slice", "bool", args)
|
||||
Argument('JS::Handle<JSObject*>', 'receiver'),
|
||||
Argument('uint32_t', 'index'),
|
||||
Argument('JS::MutableHandle<JS::Value>', 'vp'),
|
||||
Argument('bool*', 'present')]
|
||||
ClassMethod.__init__(self, "getElementIfPresent", "bool", args)
|
||||
self.descriptor = descriptor
|
||||
|
||||
def getBody(self):
|
||||
# Just like getOwnPropertyNames we'll assume that we have no holes, so
|
||||
# we have all properties from 0 to length. If that ever changes
|
||||
# (unlikely), we'll need to do something a bit more clever with how we
|
||||
# forward on to our ancestor.
|
||||
header = CGGeneric(
|
||||
'JS::Rooted<JS::Value> temp(cx);\n'
|
||||
'MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),\n'
|
||||
' "Should not have a XrayWrapper here");\n'
|
||||
'\n'
|
||||
'%s* self = UnwrapProxy(proxy);\n'
|
||||
'uint32_t length = self->Length();\n'
|
||||
"// Compute the end of the indices we'll get ourselves\n"
|
||||
'uint32_t ourEnd = std::max(begin, std::min(end, length));' %
|
||||
self.descriptor.nativeType)
|
||||
|
||||
successCode = ("js::UnsafeDefineElement(cx, array, index - begin, temp);\n"
|
||||
"continue;")
|
||||
templateValues = {'jsvalRef': 'temp', 'jsvalHandle': '&temp',
|
||||
successCode = ("*present = found;\n"
|
||||
"return true;")
|
||||
templateValues = {'jsvalRef': 'vp', 'jsvalHandle': 'vp',
|
||||
'obj': 'proxy', 'successCode': successCode}
|
||||
get = CGProxyIndexedGetter(self.descriptor, templateValues, False, False)
|
||||
if self.descriptor.supportsIndexedProperties():
|
||||
get = (CGProxyIndexedGetter(self.descriptor, templateValues).define() + "\n"
|
||||
"// We skip the expando object and any named getters if\n"
|
||||
"// there is an indexed getter.\n" +
|
||||
"\n") % (self.descriptor.nativeType)
|
||||
else:
|
||||
if self.descriptor.supportsNamedProperties():
|
||||
get = CGProxyNamedGetter(self.descriptor, templateValues,
|
||||
"UINT_TO_JSVAL(index)").define()
|
||||
get += """
|
||||
|
||||
getOurElements = CGWrapper(
|
||||
CGIndenter(get),
|
||||
pre="for (uint32_t index = begin; index < ourEnd; ++index) {\n",
|
||||
post="\n}")
|
||||
JS::Rooted<JSObject*> expando(cx, GetExpandoObject(proxy));
|
||||
if (expando) {
|
||||
bool isPresent;
|
||||
if (!JS_GetElementIfPresent(cx, expando, index, expando, vp, &isPresent)) {
|
||||
return false;
|
||||
}
|
||||
if (isPresent) {
|
||||
*present = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
getProtoElements = CGIfWrapper(
|
||||
CGGeneric("JS::Rooted<JSObject*> proto(cx);\n"
|
||||
"if (!js::GetObjectProto(cx, proxy, &proto)) {\n"
|
||||
" return false;\n"
|
||||
"}\n"
|
||||
"return js::SliceSlowly(cx, proto, proxy, ourEnd, end, array);"),
|
||||
"end > ourEnd")
|
||||
return """MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
|
||||
"Should not have a XrayWrapper here");
|
||||
|
||||
return CGList([header, getOurElements, getProtoElements,
|
||||
CGGeneric("return true;")], "\n\n").define();
|
||||
""" + get + """
|
||||
JS::Rooted<JSObject*> proto(cx);
|
||||
if (!js::GetObjectProto(cx, proxy, &proto)) {
|
||||
return false;
|
||||
}
|
||||
if (proto) {
|
||||
bool isPresent;
|
||||
if (!JS_GetElementIfPresent(cx, proto, index, proxy, vp, &isPresent)) {
|
||||
return false;
|
||||
}
|
||||
*present = isPresent;
|
||||
return true;
|
||||
}
|
||||
|
||||
*present = false;
|
||||
// Can't Debug_SetValueRangeToCrashOnTouch because it's not public
|
||||
return true;"""
|
||||
|
||||
class CGDOMJSProxyHandler_getInstance(ClassMethod):
|
||||
def __init__(self):
|
||||
|
@ -8384,11 +8366,9 @@ class CGDOMJSProxyHandler(CGClass):
|
|||
CGDOMJSProxyHandler_className(descriptor),
|
||||
CGDOMJSProxyHandler_finalizeInBackground(descriptor),
|
||||
CGDOMJSProxyHandler_finalize(descriptor),
|
||||
CGDOMJSProxyHandler_getElementIfPresent(descriptor),
|
||||
CGDOMJSProxyHandler_getInstance(),
|
||||
CGDOMJSProxyHandler_delete(descriptor)]
|
||||
if descriptor.supportsIndexedProperties():
|
||||
methods.append(CGDOMJSProxyHandler_slice(descriptor))
|
||||
|
||||
CGClass.__init__(self, 'DOMProxyHandler',
|
||||
bases=[ClassBase('mozilla::dom::DOMProxyHandler')],
|
||||
constructors=constructors,
|
||||
|
|
|
@ -169,11 +169,7 @@ function expandPermissions(aPerms) {
|
|||
aPerms.forEach(function(el) {
|
||||
var access = permTable[el].access ? "readwrite" : null;
|
||||
var expanded = SpecialPowers.unwrap(expand(el, access));
|
||||
// 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]);
|
||||
}
|
||||
perms = perms.concat(expanded.slice(0));
|
||||
});
|
||||
|
||||
return perms;
|
||||
|
|
|
@ -347,6 +347,9 @@ typedef bool
|
|||
(* ElementIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, uint32_t index,
|
||||
JS::MutableHandleValue vp);
|
||||
typedef bool
|
||||
(* ElementIfPresentOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver,
|
||||
uint32_t index, JS::MutableHandleValue vp, bool* present);
|
||||
typedef bool
|
||||
(* SpecialIdOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver,
|
||||
HandleSpecialId sid, JS::MutableHandleValue vp);
|
||||
typedef bool
|
||||
|
@ -380,10 +383,6 @@ 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
|
||||
|
@ -460,6 +459,7 @@ struct ObjectOps
|
|||
GenericIdOp getGeneric;
|
||||
PropertyIdOp getProperty;
|
||||
ElementIdOp getElement;
|
||||
ElementIfPresentOp getElementIfPresent; /* can be null */
|
||||
SpecialIdOp getSpecial;
|
||||
StrictGenericIdOp setGeneric;
|
||||
StrictPropertyIdOp setProperty;
|
||||
|
@ -472,7 +472,6 @@ struct ObjectOps
|
|||
DeleteSpecialOp deleteSpecial;
|
||||
WatchOp watch;
|
||||
UnwatchOp unwatch;
|
||||
SliceOp slice; // Optimized slice, can be null.
|
||||
|
||||
JSNewEnumerateOp enumerate;
|
||||
ObjectOp thisObject;
|
||||
|
@ -481,7 +480,7 @@ struct ObjectOps
|
|||
#define JS_NULL_OBJECT_OPS \
|
||||
{nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, \
|
||||
nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, \
|
||||
nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}
|
||||
nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}
|
||||
|
||||
} // namespace js
|
||||
|
||||
|
|
|
@ -2054,6 +2054,15 @@ TypedDatum::obj_getProperty(JSContext *cx, HandleObject obj, HandleObject receiv
|
|||
bool
|
||||
TypedDatum::obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
uint32_t index, MutableHandleValue vp)
|
||||
{
|
||||
bool present;
|
||||
return obj_getElementIfPresent(cx, obj, receiver, index, vp, &present);
|
||||
}
|
||||
|
||||
bool
|
||||
TypedDatum::obj_getElementIfPresent(JSContext *cx, HandleObject obj,
|
||||
HandleObject receiver, uint32_t index,
|
||||
MutableHandleValue vp, bool *present)
|
||||
{
|
||||
RootedObject type(cx, GetType(*obj));
|
||||
TypeRepresentation *typeRepr = typeRepresentation(*type);
|
||||
|
@ -2066,6 +2075,7 @@ TypedDatum::obj_getElement(JSContext *cx, HandleObject obj, HandleObject receive
|
|||
break;
|
||||
|
||||
case TypeRepresentation::Array: {
|
||||
*present = true;
|
||||
ArrayTypeRepresentation *arrayTypeRepr = typeRepr->asArray();
|
||||
|
||||
if (index >= arrayTypeRepr->length()) {
|
||||
|
@ -2081,11 +2091,12 @@ TypedDatum::obj_getElement(JSContext *cx, HandleObject obj, HandleObject receive
|
|||
|
||||
RootedObject proto(cx, obj->getProto());
|
||||
if (!proto) {
|
||||
*present = false;
|
||||
vp.setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
return JSObject::getElement(cx, proto, receiver, index, vp);
|
||||
return JSObject::getElementIfPresent(cx, proto, receiver, index, vp, present);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2450,6 +2461,7 @@ const Class TypedObject::class_ = {
|
|||
TypedDatum::obj_getGeneric,
|
||||
TypedDatum::obj_getProperty,
|
||||
TypedDatum::obj_getElement,
|
||||
TypedDatum::obj_getElementIfPresent,
|
||||
TypedDatum::obj_getSpecial,
|
||||
TypedDatum::obj_setGeneric,
|
||||
TypedDatum::obj_setProperty,
|
||||
|
@ -2461,7 +2473,6 @@ const Class TypedObject::class_ = {
|
|||
TypedDatum::obj_deleteElement,
|
||||
TypedDatum::obj_deleteSpecial,
|
||||
nullptr, nullptr, // watch/unwatch
|
||||
nullptr, // slice
|
||||
TypedDatum::obj_enumerate,
|
||||
nullptr, /* thisObject */
|
||||
}
|
||||
|
@ -2542,6 +2553,7 @@ const Class TypedHandle::class_ = {
|
|||
TypedDatum::obj_getGeneric,
|
||||
TypedDatum::obj_getProperty,
|
||||
TypedDatum::obj_getElement,
|
||||
TypedDatum::obj_getElementIfPresent,
|
||||
TypedDatum::obj_getSpecial,
|
||||
TypedDatum::obj_setGeneric,
|
||||
TypedDatum::obj_setProperty,
|
||||
|
@ -2553,7 +2565,6 @@ const Class TypedHandle::class_ = {
|
|||
TypedDatum::obj_deleteElement,
|
||||
TypedDatum::obj_deleteSpecial,
|
||||
nullptr, nullptr, // watch/unwatch
|
||||
nullptr, // slice
|
||||
TypedDatum::obj_enumerate,
|
||||
nullptr, /* thisObject */
|
||||
}
|
||||
|
|
|
@ -268,6 +268,9 @@ class TypedDatum : public JSObject
|
|||
static bool obj_getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
HandleSpecialId sid, MutableHandleValue vp);
|
||||
|
||||
static bool obj_getElementIfPresent(JSContext *cx, HandleObject obj,
|
||||
HandleObject receiver, uint32_t index,
|
||||
MutableHandleValue vp, bool *present);
|
||||
static bool obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
||||
MutableHandleValue vp, bool strict);
|
||||
static bool obj_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
let invoked = false;
|
||||
Object.defineProperty(Array.prototype, '0', {set: function () {
|
||||
invoked = true;
|
||||
}});
|
||||
|
||||
let result = [1, 2, 3].slice(1);
|
||||
assertEq(invoked, false);
|
||||
|
||||
let proxy = new Proxy({}, {
|
||||
get: function (target, name, proxy) {
|
||||
switch (name) {
|
||||
case "length":
|
||||
return 2;
|
||||
case "0":
|
||||
return 15;
|
||||
case "1":
|
||||
// Should not invoke [[Get]] for this hole.
|
||||
default:
|
||||
assertEq(false, true);
|
||||
}
|
||||
},
|
||||
has: function (target, name) {
|
||||
switch (name) {
|
||||
case "0":
|
||||
return true;
|
||||
case "1":
|
||||
return false;
|
||||
default:
|
||||
assertEq(false, true);
|
||||
}
|
||||
}
|
||||
})
|
||||
result = Array.prototype.slice.call(proxy, 0);
|
||||
assertEq(result.length, 2);
|
||||
assertEq(0 in result, true);
|
||||
assertEq(1 in result, false);
|
||||
assertEq(result[0], 15);
|
|
@ -3393,6 +3393,25 @@ JS_ForwardGetElementTo(JSContext *cx, JSObject *objArg, uint32_t index, JSObject
|
|||
return JSObject::getElement(cx, obj, onBehalfOf, index, vp);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_GetElementIfPresent(JSContext *cx, JSObject *objArg, uint32_t index, JSObject *onBehalfOfArg,
|
||||
MutableHandleValue vp, bool* present)
|
||||
{
|
||||
RootedObject obj(cx, objArg);
|
||||
RootedObject onBehalfOf(cx, onBehalfOfArg);
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj);
|
||||
JSAutoResolveFlags rf(cx, 0);
|
||||
|
||||
bool isPresent;
|
||||
if (!JSObject::getElementIfPresent(cx, obj, onBehalfOf, index, vp, &isPresent))
|
||||
return false;
|
||||
|
||||
*present = isPresent;
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_GetProperty(JSContext *cx, JSObject *objArg, const char *name, MutableHandleValue vp)
|
||||
{
|
||||
|
|
|
@ -3040,6 +3040,15 @@ extern JS_PUBLIC_API(bool)
|
|||
JS_ForwardGetElementTo(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf,
|
||||
JS::MutableHandle<JS::Value> vp);
|
||||
|
||||
/*
|
||||
* Get the property with name given by |index|, if it has one. If
|
||||
* not, |*present| will be set to false and the value of |vp| must not
|
||||
* be relied on.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_GetElementIfPresent(JSContext *cx, JSObject *obj, uint32_t index, JSObject *onBehalfOf,
|
||||
JS::MutableHandle<JS::Value> vp, bool* present);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_SetElement(JSContext *cx, JSObject *obj, uint32_t index, JS::MutableHandle<JS::Value> vp);
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ js::StringIsArrayIndex(JSLinearString *str, uint32_t *indexp)
|
|||
}
|
||||
|
||||
static bool
|
||||
ToId(JSContext *cx, double index, MutableHandleId id)
|
||||
DoubleIndexToId(JSContext *cx, double index, MutableHandleId id)
|
||||
{
|
||||
if (index == uint32_t(index))
|
||||
return IndexToId(cx, uint32_t(index), id.address());
|
||||
|
@ -143,26 +143,18 @@ ToId(JSContext *cx, double index, MutableHandleId id)
|
|||
return ValueToId<CanGC>(cx, HandleValue::fromMarkedLocation(&tmp), id);
|
||||
}
|
||||
|
||||
static bool
|
||||
ToId(JSContext *cx, uint32_t index, MutableHandleId id)
|
||||
{
|
||||
return IndexToId(cx, index, id.address());
|
||||
}
|
||||
|
||||
/*
|
||||
* If the property at the given index exists, get its value into location
|
||||
* pointed by vp and set *hole to false. Otherwise set *hole to true and *vp
|
||||
* to JSVAL_VOID. This function assumes that the location pointed by vp is
|
||||
* properly rooted and can be used as GC-protected storage for temporaries.
|
||||
*/
|
||||
template<typename IndexType>
|
||||
static inline bool
|
||||
DoGetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
IndexType index, bool *hole, MutableHandleValue vp)
|
||||
DoGetElement(JSContext *cx, HandleObject obj, double index, bool *hole, MutableHandleValue vp)
|
||||
{
|
||||
RootedId id(cx);
|
||||
|
||||
if (!ToId(cx, index, &id))
|
||||
if (!DoubleIndexToId(cx, index, &id))
|
||||
return false;
|
||||
|
||||
RootedObject obj2(cx);
|
||||
|
@ -174,13 +166,27 @@ DoGetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
|||
vp.setUndefined();
|
||||
*hole = true;
|
||||
} else {
|
||||
if (!JSObject::getGeneric(cx, obj, receiver, id, vp))
|
||||
if (!JSObject::getGeneric(cx, obj, obj, id, vp))
|
||||
return false;
|
||||
*hole = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
DoGetElement(JSContext *cx, HandleObject obj, uint32_t index, bool *hole, MutableHandleValue vp)
|
||||
{
|
||||
bool present;
|
||||
if (!JSObject::getElementIfPresent(cx, obj, obj, index, vp, &present))
|
||||
return false;
|
||||
|
||||
*hole = !present;
|
||||
if (*hole)
|
||||
vp.setUndefined();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename IndexType>
|
||||
static void
|
||||
AssertGreaterThanZero(IndexType index)
|
||||
|
@ -197,8 +203,7 @@ AssertGreaterThanZero(uint32_t index)
|
|||
|
||||
template<typename IndexType>
|
||||
static bool
|
||||
GetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
IndexType index, bool *hole, MutableHandleValue vp)
|
||||
GetElement(JSContext *cx, HandleObject obj, IndexType index, bool *hole, MutableHandleValue vp)
|
||||
{
|
||||
AssertGreaterThanZero(index);
|
||||
if (obj->isNative() && index < obj->getDenseInitializedLength()) {
|
||||
|
@ -215,14 +220,7 @@ GetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
|||
}
|
||||
}
|
||||
|
||||
return DoGetElement(cx, obj, receiver, index, hole, vp);
|
||||
}
|
||||
|
||||
template<typename IndexType>
|
||||
static inline bool
|
||||
GetElement(JSContext *cx, HandleObject obj, IndexType index, bool *hole, MutableHandleValue vp)
|
||||
{
|
||||
return GetElement(cx, obj, obj, index, hole, vp);
|
||||
return DoGetElement(cx, obj, index, hole, vp);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -298,7 +296,7 @@ SetArrayElement(JSContext *cx, HandleObject obj, double index, HandleValue v)
|
|||
}
|
||||
|
||||
RootedId id(cx);
|
||||
if (!ToId(cx, index, &id))
|
||||
if (!DoubleIndexToId(cx, index, &id))
|
||||
return false;
|
||||
|
||||
RootedValue tmp(cx, v);
|
||||
|
@ -2682,18 +2680,20 @@ 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))
|
||||
|
@ -2741,50 +2741,20 @@ array_slice(JSContext *cx, unsigned argc, Value *vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (js::SliceOp op = obj->getOps()->slice) {
|
||||
// Ensure that we have dense elements, so that DOM can use js::UnsafeDefineElement.
|
||||
JSObject::EnsureDenseResult result = narr->ensureDenseElements(cx, 0, end - begin);
|
||||
if (result == JSObject::ED_FAILED)
|
||||
return false;
|
||||
|
||||
if (result == JSObject::ED_OK) {
|
||||
if (!op(cx, obj, begin, end, narr))
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*narr);
|
||||
return true;
|
||||
RootedValue value(cx);
|
||||
for (slot = begin; slot < end; slot++) {
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx) ||
|
||||
!GetElement(cx, obj, slot, &hole, &value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fallthrough
|
||||
JS_ASSERT(result == JSObject::ED_SPARSE);
|
||||
if (!hole && !SetArrayElement(cx, narr, slot - begin, value))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!SliceSlowly(cx, obj, obj, begin, end, narr))
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*narr);
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
js::SliceSlowly(JSContext* cx, HandleObject obj, HandleObject receiver,
|
||||
uint32_t begin, uint32_t end, HandleObject result)
|
||||
{
|
||||
RootedValue value(cx);
|
||||
for (uint32_t slot = begin; slot < end; slot++) {
|
||||
bool hole;
|
||||
if (!JS_CHECK_OPERATION_LIMIT(cx) ||
|
||||
!GetElement(cx, obj, receiver, slot, &hole, &value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!hole && !JSObject::defineElement(cx, result, slot - begin, value))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ES5 15.4.4.20. */
|
||||
static bool
|
||||
array_filter(JSContext *cx, unsigned argc, Value *vp)
|
||||
|
|
|
@ -1165,14 +1165,6 @@ js::GetObjectMetadata(JSObject *obj)
|
|||
return obj->getMetadata();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::UnsafeDefineElement(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value)
|
||||
{
|
||||
JS_ASSERT(obj->isNative());
|
||||
JS_ASSERT(index < obj->getDenseInitializedLength());
|
||||
obj->setDenseElementWithType(cx, index, value);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
js_DefineOwnProperty(JSContext *cx, JSObject *objArg, jsid idArg,
|
||||
JS::Handle<js::PropertyDescriptor> descriptor, bool *bp)
|
||||
|
|
|
@ -1739,13 +1739,6 @@ SetObjectMetadata(JSContext *cx, JS::HandleObject obj, JS::HandleObject metadata
|
|||
JS_FRIEND_API(JSObject *)
|
||||
GetObjectMetadata(JSObject *obj);
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
UnsafeDefineElement(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value);
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
SliceSlowly(JSContext* cx, JS::HandleObject obj, JS::HandleObject receiver,
|
||||
uint32_t begin, uint32_t end, JS::HandleObject result);
|
||||
|
||||
/* ES5 8.12.8. */
|
||||
extern JS_FRIEND_API(bool)
|
||||
DefaultValue(JSContext *cx, JS::HandleObject obj, JSType hint, JS::MutableHandleValue vp);
|
||||
|
|
|
@ -1030,6 +1030,12 @@ class JSObject : public js::ObjectImpl
|
|||
static inline bool getElementNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
|
||||
uint32_t index, js::Value *vp);
|
||||
|
||||
/* If element is not present (e.g. array hole) *present is set to
|
||||
false and the contents of *vp are unusable garbage. */
|
||||
static inline bool getElementIfPresent(JSContext *cx, js::HandleObject obj,
|
||||
js::HandleObject receiver, uint32_t index,
|
||||
js::MutableHandleValue vp, bool *present);
|
||||
|
||||
static bool getSpecial(JSContext *cx, js::HandleObject obj,
|
||||
js::HandleObject receiver, js::SpecialId sid,
|
||||
js::MutableHandleValue vp)
|
||||
|
|
|
@ -583,6 +583,38 @@ JSObject::getElementNoGC(JSContext *cx, JSObject *obj, JSObject *receiver,
|
|||
return getGenericNoGC(cx, obj, receiver, id, vp);
|
||||
}
|
||||
|
||||
/* static */ inline bool
|
||||
JSObject::getElementIfPresent(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
|
||||
uint32_t index, js::MutableHandleValue vp,
|
||||
bool *present)
|
||||
{
|
||||
js::ElementIfPresentOp op = obj->getOps()->getElementIfPresent;
|
||||
if (op)
|
||||
return op(cx, obj, receiver, index, vp, present);
|
||||
|
||||
/*
|
||||
* For now, do the index-to-id conversion just once, then use
|
||||
* lookupGeneric/getGeneric. Once lookupElement and getElement stop both
|
||||
* doing index-to-id conversions, we can use those here.
|
||||
*/
|
||||
JS::RootedId id(cx);
|
||||
if (!js::IndexToId(cx, index, id.address()))
|
||||
return false;
|
||||
|
||||
JS::RootedObject obj2(cx);
|
||||
js::RootedShape prop(cx);
|
||||
if (!lookupGeneric(cx, obj, id, &obj2, &prop))
|
||||
return false;
|
||||
|
||||
if (!prop) {
|
||||
*present = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
*present = true;
|
||||
return getGeneric(cx, obj, receiver, id, vp);
|
||||
}
|
||||
|
||||
inline js::GlobalObject &
|
||||
JSObject::global() const
|
||||
{
|
||||
|
|
|
@ -151,6 +151,27 @@ BaseProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
|||
return CallJSPropertyOp(cx, desc.getter(), receiver, id, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
BaseProxyHandler::getElementIfPresent(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
||||
uint32_t index, MutableHandleValue vp, bool *present)
|
||||
{
|
||||
RootedId id(cx);
|
||||
if (!IndexToId(cx, index, id.address()))
|
||||
return false;
|
||||
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
|
||||
if (!has(cx, proxy, id, present))
|
||||
return false;
|
||||
|
||||
if (!*present) {
|
||||
Debug_SetValueRangeToCrashOnTouch(vp.address(), 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return get(cx, proxy, receiver, id, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
BaseProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
||||
HandleId id, bool strict, MutableHandleValue vp)
|
||||
|
@ -364,34 +385,6 @@ 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)
|
||||
|
@ -2526,6 +2519,41 @@ Proxy::callProp(JSContext *cx, HandleObject proxy, HandleObject receiver, Handle
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Proxy::getElementIfPresent(JSContext *cx, HandleObject proxy, HandleObject receiver, uint32_t index,
|
||||
MutableHandleValue vp, bool *present)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
|
||||
RootedId id(cx);
|
||||
if (!IndexToId(cx, index, id.address()))
|
||||
return false;
|
||||
|
||||
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
|
||||
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true);
|
||||
if (!policy.allowed())
|
||||
return policy.returnValue();
|
||||
|
||||
if (!handler->hasPrototype()) {
|
||||
return handler->getElementIfPresent(cx, proxy, receiver, index,
|
||||
vp, present);
|
||||
}
|
||||
|
||||
bool hasOwn;
|
||||
if (!handler->hasOwn(cx, proxy, id, &hasOwn))
|
||||
return false;
|
||||
|
||||
if (hasOwn) {
|
||||
*present = true;
|
||||
return proxy->as<ProxyObject>().handler()->get(cx, proxy, receiver, id, vp);
|
||||
}
|
||||
|
||||
*present = false;
|
||||
INVOKE_ON_PROTOTYPE(cx, handler, proxy,
|
||||
JSObject::getElementIfPresent(cx, proto, receiver, index, vp, present));
|
||||
}
|
||||
|
||||
bool
|
||||
Proxy::set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id, bool strict,
|
||||
MutableHandleValue vp)
|
||||
|
@ -2748,18 +2776,6 @@ 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)
|
||||
{
|
||||
|
@ -2875,6 +2891,13 @@ proxy_GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_
|
|||
return proxy_GetGeneric(cx, obj, receiver, id, vp);
|
||||
}
|
||||
|
||||
static bool
|
||||
proxy_GetElementIfPresent(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index,
|
||||
MutableHandleValue vp, bool *present)
|
||||
{
|
||||
return Proxy::getElementIfPresent(cx, obj, receiver, index, vp, present);
|
||||
}
|
||||
|
||||
static bool
|
||||
proxy_GetSpecial(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid,
|
||||
MutableHandleValue vp)
|
||||
|
@ -3053,24 +3076,17 @@ proxy_Construct(JSContext *cx, unsigned argc, Value *vp)
|
|||
}
|
||||
|
||||
static bool
|
||||
proxy_Watch(JSContext *cx, HandleObject obj, HandleId id, HandleObject callable)
|
||||
proxy_Watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable)
|
||||
{
|
||||
return Proxy::watch(cx, obj, id, callable);
|
||||
}
|
||||
|
||||
static bool
|
||||
proxy_Unwatch(JSContext *cx, HandleObject obj, HandleId id)
|
||||
proxy_Unwatch(JSContext *cx, JS::HandleObject obj, JS::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 */ \
|
||||
|
@ -3112,6 +3128,7 @@ proxy_Slice(JSContext *cx, HandleObject proxy, uint32_t begin, uint32_t end,
|
|||
proxy_GetGeneric, \
|
||||
proxy_GetProperty, \
|
||||
proxy_GetElement, \
|
||||
proxy_GetElementIfPresent, \
|
||||
proxy_GetSpecial, \
|
||||
proxy_SetGeneric, \
|
||||
proxy_SetProperty, \
|
||||
|
@ -3123,7 +3140,6 @@ proxy_Slice(JSContext *cx, HandleObject proxy, uint32_t begin, uint32_t end,
|
|||
proxy_DeleteElement, \
|
||||
proxy_DeleteSpecial, \
|
||||
proxy_Watch, proxy_Unwatch, \
|
||||
proxy_Slice, \
|
||||
nullptr, /* enumerate */ \
|
||||
nullptr, /* thisObject */ \
|
||||
} \
|
||||
|
@ -3170,6 +3186,7 @@ const Class js::OuterWindowProxyObject::class_ = {
|
|||
proxy_GetGeneric,
|
||||
proxy_GetProperty,
|
||||
proxy_GetElement,
|
||||
proxy_GetElementIfPresent,
|
||||
proxy_GetSpecial,
|
||||
proxy_SetGeneric,
|
||||
proxy_SetProperty,
|
||||
|
@ -3181,7 +3198,6 @@ const Class js::OuterWindowProxyObject::class_ = {
|
|||
proxy_DeleteElement,
|
||||
proxy_DeleteSpecial,
|
||||
proxy_Watch, proxy_Unwatch,
|
||||
proxy_Slice,
|
||||
nullptr, /* enumerate */
|
||||
nullptr, /* thisObject */
|
||||
}
|
||||
|
|
|
@ -166,6 +166,8 @@ class JS_FRIEND_API(BaseProxyHandler)
|
|||
virtual bool regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g);
|
||||
virtual bool defaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp);
|
||||
virtual void finalize(JSFreeOp *fop, JSObject *proxy);
|
||||
virtual bool getElementIfPresent(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
uint32_t index, MutableHandleValue vp, bool *present);
|
||||
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop);
|
||||
|
||||
// These two hooks must be overridden, or not overridden, in tandem -- no
|
||||
|
@ -174,9 +176,6 @@ 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; }
|
||||
|
@ -277,6 +276,8 @@ class Proxy
|
|||
static bool hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp);
|
||||
static bool get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
|
||||
MutableHandleValue vp);
|
||||
static bool getElementIfPresent(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
||||
uint32_t index, MutableHandleValue vp, bool *present);
|
||||
static bool set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
|
||||
bool strict, MutableHandleValue vp);
|
||||
static bool keys(JSContext *cx, HandleObject proxy, AutoIdVector &props);
|
||||
|
@ -295,11 +296,9 @@ 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, 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);
|
||||
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);
|
||||
|
||||
/* IC entry path for handling __noSuchMethod__ on access. */
|
||||
static bool callProp(JSContext *cx, HandleObject proxy, HandleObject reveiver, HandleId id,
|
||||
|
|
|
@ -839,6 +839,14 @@ DeadObjectProxy::defaultValue(JSContext *cx, HandleObject obj, JSType hint, Muta
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
DeadObjectProxy::getElementIfPresent(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
uint32_t index, MutableHandleValue vp, bool *present)
|
||||
{
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
DeadObjectProxy::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop)
|
||||
{
|
||||
|
|
|
@ -208,6 +208,9 @@ class JS_FRIEND_API(DeadObjectProxy) : public BaseProxyHandler
|
|||
virtual bool regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g) MOZ_OVERRIDE;
|
||||
virtual bool defaultValue(JSContext *cx, HandleObject obj, JSType hint,
|
||||
MutableHandleValue vp) MOZ_OVERRIDE;
|
||||
virtual bool getElementIfPresent(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
uint32_t index, MutableHandleValue vp,
|
||||
bool *present) MOZ_OVERRIDE;
|
||||
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy,
|
||||
MutableHandleObject protop) MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -557,6 +557,7 @@ const Class WithObject::class_ = {
|
|||
with_GetGeneric,
|
||||
with_GetProperty,
|
||||
with_GetElement,
|
||||
nullptr, /* getElementIfPresent */
|
||||
with_GetSpecial,
|
||||
with_SetGeneric,
|
||||
with_SetProperty,
|
||||
|
@ -567,8 +568,7 @@ const Class WithObject::class_ = {
|
|||
with_DeleteProperty,
|
||||
with_DeleteElement,
|
||||
with_DeleteSpecial,
|
||||
nullptr, nullptr, /* watch/unwatch */
|
||||
nullptr, /* slice */
|
||||
nullptr, nullptr, /* watch/unwatch */
|
||||
with_Enumerate,
|
||||
with_ThisObject,
|
||||
}
|
||||
|
|
|
@ -1037,6 +1037,16 @@ ArrayBufferObject::obj_getElement(JSContext *cx, HandleObject obj,
|
|||
return baseops::GetElement(cx, delegate, receiver, index, vp);
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayBufferObject::obj_getElementIfPresent(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
uint32_t index, MutableHandleValue vp, bool *present)
|
||||
{
|
||||
RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
|
||||
if (!delegate)
|
||||
return false;
|
||||
return JSObject::getElementIfPresent(cx, delegate, receiver, index, vp, present);
|
||||
}
|
||||
|
||||
bool
|
||||
ArrayBufferObject::obj_getSpecial(JSContext *cx, HandleObject obj,
|
||||
HandleObject receiver, HandleSpecialId sid,
|
||||
|
@ -1484,6 +1494,27 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
|||
return obj_getProperty(cx, obj, receiver, name, vp);
|
||||
}
|
||||
|
||||
static bool
|
||||
obj_getElementIfPresent(JSContext *cx, HandleObject tarray, HandleObject receiver, uint32_t index,
|
||||
MutableHandleValue vp, bool *present)
|
||||
{
|
||||
// Fast-path the common case of index < length
|
||||
if (index < tarray->as<TypedArrayObject>().length()) {
|
||||
// this inline function is specialized for each type
|
||||
copyIndexToValue(tarray, index, vp);
|
||||
*present = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedObject proto(cx, tarray->getProto());
|
||||
if (!proto) {
|
||||
vp.setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
return JSObject::getElementIfPresent(cx, proto, receiver, index, vp, present);
|
||||
}
|
||||
|
||||
static bool
|
||||
setElementTail(JSContext *cx, HandleObject tarray, uint32_t index,
|
||||
MutableHandleValue vp, bool strict)
|
||||
|
@ -3449,6 +3480,7 @@ const Class ArrayBufferObject::class_ = {
|
|||
ArrayBufferObject::obj_getGeneric,
|
||||
ArrayBufferObject::obj_getProperty,
|
||||
ArrayBufferObject::obj_getElement,
|
||||
ArrayBufferObject::obj_getElementIfPresent,
|
||||
ArrayBufferObject::obj_getSpecial,
|
||||
ArrayBufferObject::obj_setGeneric,
|
||||
ArrayBufferObject::obj_setProperty,
|
||||
|
@ -3460,9 +3492,8 @@ const Class ArrayBufferObject::class_ = {
|
|||
ArrayBufferObject::obj_deleteElement,
|
||||
ArrayBufferObject::obj_deleteSpecial,
|
||||
nullptr, nullptr, /* watch/unwatch */
|
||||
nullptr, /* slice */
|
||||
ArrayBufferObject::obj_enumerate,
|
||||
nullptr, /* thisObject */
|
||||
nullptr, /* thisObject */
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3612,6 +3643,7 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double)
|
|||
_typedArray##Object::obj_getGeneric, \
|
||||
_typedArray##Object::obj_getProperty, \
|
||||
_typedArray##Object::obj_getElement, \
|
||||
_typedArray##Object::obj_getElementIfPresent, \
|
||||
_typedArray##Object::obj_getSpecial, \
|
||||
_typedArray##Object::obj_setGeneric, \
|
||||
_typedArray##Object::obj_setProperty, \
|
||||
|
@ -3623,9 +3655,8 @@ 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 */ \
|
||||
} \
|
||||
}
|
||||
|
||||
|
|
|
@ -107,6 +107,8 @@ class ArrayBufferObject : public JSObject
|
|||
|
||||
static bool obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
uint32_t index, MutableHandleValue vp);
|
||||
static bool obj_getElementIfPresent(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
uint32_t index, MutableHandleValue vp, bool *present);
|
||||
|
||||
static bool obj_getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||
HandleSpecialId sid, MutableHandleValue vp);
|
||||
|
|
|
@ -720,6 +720,7 @@ const XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass = {
|
|||
nullptr, // getGeneric
|
||||
nullptr, // getProperty
|
||||
nullptr, // getElement
|
||||
nullptr, // getElementIfPresent
|
||||
nullptr, // getSpecial
|
||||
nullptr, // setGeneric
|
||||
nullptr, // setProperty
|
||||
|
@ -731,7 +732,6 @@ const XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass = {
|
|||
nullptr, // deleteElement
|
||||
nullptr, // deleteSpecial
|
||||
nullptr, nullptr, // watch/unwatch
|
||||
nullptr, // slice
|
||||
XPC_WN_JSOp_Enumerate,
|
||||
XPC_WN_JSOp_ThisObject,
|
||||
}
|
||||
|
|
|
@ -982,6 +982,7 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS::HandleObject obj);
|
|||
nullptr, /* getGeneric */ \
|
||||
nullptr, /* getProperty */ \
|
||||
nullptr, /* getElement */ \
|
||||
nullptr, /* getElementIfPresent */ \
|
||||
nullptr, /* getSpecial */ \
|
||||
nullptr, /* setGeneric */ \
|
||||
nullptr, /* setProperty */ \
|
||||
|
@ -993,7 +994,6 @@ 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, \
|
||||
}
|
||||
|
@ -1011,6 +1011,7 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS::HandleObject obj);
|
|||
nullptr, /* getGeneric */ \
|
||||
nullptr, /* getProperty */ \
|
||||
nullptr, /* getElement */ \
|
||||
nullptr, /* getElementIfPresent */ \
|
||||
nullptr, /* getSpecial */ \
|
||||
nullptr, /* setGeneric */ \
|
||||
nullptr, /* setProperty */ \
|
||||
|
@ -1022,7 +1023,6 @@ 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, \
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче