mirror of
https://github.com/classilla/tenfourfox.git
synced 2025-01-01 06:33:22 +00:00
#428: optimized Object.values and Object.entries from M1232369
This commit is contained in:
parent
127ef91c91
commit
af74f27ed9
@ -680,7 +680,109 @@ js::obj_getOwnPropertyDescriptor(JSContext* cx, unsigned argc, Value* vp)
|
||||
FromPropertyDescriptor(cx, desc, args.rval());
|
||||
}
|
||||
|
||||
// ES6 draft rev27 (2014/08/24) 19.1.2.14 Object.keys(O)
|
||||
enum EnumerableOwnPropertiesKind {
|
||||
Keys,
|
||||
Values,
|
||||
KeysAndValues
|
||||
};
|
||||
|
||||
// ES7 proposal 2015-12-14
|
||||
// http://tc39.github.io/proposal-object-values-entries/#EnumerableOwnProperties
|
||||
static bool
|
||||
EnumerableOwnProperties(JSContext* cx, const JS::CallArgs& args, EnumerableOwnPropertiesKind kind)
|
||||
{
|
||||
// Step 1. (Step 1 of Object.{keys,values,entries}, really.)
|
||||
RootedObject obj(cx, ToObject(cx, args.get(0)));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
// Step 2.
|
||||
AutoIdVector ids(cx);
|
||||
if (!GetPropertyKeys(cx, obj, JSITER_OWNONLY | JSITER_HIDDEN, &ids))
|
||||
return false;
|
||||
|
||||
// Step 3.
|
||||
AutoValueVector properties(cx);
|
||||
size_t len = ids.length();
|
||||
if (!properties.resize(len))
|
||||
return false;
|
||||
|
||||
RootedId id(cx);
|
||||
RootedValue key(cx);
|
||||
RootedValue value(cx);
|
||||
RootedNativeObject nobj(cx);
|
||||
if (obj->is<NativeObject>())
|
||||
nobj = &obj->as<NativeObject>();
|
||||
RootedShape shape(cx);
|
||||
Rooted<PropertyDescriptor> desc(cx);
|
||||
|
||||
// Step 4.
|
||||
size_t out = 0;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
id = ids[i];
|
||||
|
||||
// Step 4.a. (Symbols were filtered out in step 2.)
|
||||
MOZ_ASSERT(!JSID_IS_SYMBOL(id));
|
||||
|
||||
if (kind != Values) {
|
||||
if (!IdToStringOrSymbol(cx, id, &key))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 4.a.i.
|
||||
if (nobj) {
|
||||
if (JSID_IS_INT(id) && nobj->containsDenseElement(JSID_TO_INT(id))) {
|
||||
value = nobj->getDenseOrTypedArrayElement(JSID_TO_INT(id));
|
||||
} else {
|
||||
shape = nobj->lookup(cx, id);
|
||||
if (!shape || !(GetShapeAttributes(nobj, shape) & JSPROP_ENUMERATE))
|
||||
continue;
|
||||
if (!shape->isAccessorShape()) {
|
||||
if (!NativeGetExistingProperty(cx, nobj, nobj, shape, &value))
|
||||
return false;
|
||||
} else if (!GetProperty(cx, obj, obj, id, &value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!GetOwnPropertyDescriptor(cx, obj, id, &desc))
|
||||
return false;
|
||||
|
||||
// Step 4.a.ii. (inverted.)
|
||||
if (!desc.object() || !desc.enumerable())
|
||||
continue;
|
||||
|
||||
// Step 4.a.ii.1.
|
||||
// (Omitted because Object.keys doesn't use this implementation.)
|
||||
|
||||
// Step 4.a.ii.2.a.
|
||||
if (obj->isNative() && desc.hasValue())
|
||||
value = desc.value();
|
||||
else if (!GetProperty(cx, obj, obj, id, &value))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Steps 4.a.ii.2.b-c.
|
||||
if (kind == Values)
|
||||
properties[out++].set(value);
|
||||
else if (!NewValuePair(cx, key, value, properties[out++]))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
// (Implemented in step 2.)
|
||||
|
||||
// Step 3 of Object.{keys,values,entries}
|
||||
JSObject* aobj = NewDenseCopiedArray(cx, out, properties.begin());
|
||||
if (!aobj)
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*aobj);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ES7 proposal 2015-12-14
|
||||
// http://tc39.github.io/proposal-object-values-entries/#Object.keys
|
||||
static bool
|
||||
obj_keys(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
@ -688,6 +790,24 @@ obj_keys(JSContext* cx, unsigned argc, Value* vp)
|
||||
return GetOwnPropertyKeys(cx, args, JSITER_OWNONLY);
|
||||
}
|
||||
|
||||
// ES7 proposal 2015-12-14
|
||||
// http://tc39.github.io/proposal-object-values-entries/#Object.values
|
||||
static bool
|
||||
obj_values(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return EnumerableOwnProperties(cx, args, Values);
|
||||
}
|
||||
|
||||
// ES7 proposal 2015-12-14
|
||||
// http://tc39.github.io/proposal-object-values-entries/#Object.entries
|
||||
static bool
|
||||
obj_entries(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return EnumerableOwnProperties(cx, args, KeysAndValues);
|
||||
}
|
||||
|
||||
/* ES6 draft 15.2.3.16 */
|
||||
static bool
|
||||
obj_is(JSContext* cx, unsigned argc, Value* vp)
|
||||
@ -1009,10 +1129,8 @@ static const JSFunctionSpec object_static_methods[] = {
|
||||
JS_FN("setPrototypeOf", obj_setPrototypeOf, 2, 0),
|
||||
JS_FN("getOwnPropertyDescriptor", obj_getOwnPropertyDescriptor,2, 0),
|
||||
JS_FN("keys", obj_keys, 1, 0),
|
||||
#ifndef RELEASE_BUILD
|
||||
JS_SELF_HOSTED_FN("values", "ObjectValues", 1, JSPROP_DEFINE_LATE),
|
||||
JS_SELF_HOSTED_FN("entries", "ObjectEntries", 1, JSPROP_DEFINE_LATE),
|
||||
#endif
|
||||
JS_FN("values", obj_values, 1, 0),
|
||||
JS_FN("entries", obj_entries, 1, 0),
|
||||
JS_FN("is", obj_is, 2, 0),
|
||||
JS_FN("defineProperty", obj_defineProperty, 3, 0),
|
||||
JS_FN("defineProperties", obj_defineProperties, 2, 0),
|
||||
|
@ -133,49 +133,3 @@ function ObjectLookupGetter(name) {
|
||||
object = std_Reflect_getPrototypeOf(object);
|
||||
} while (object !== null);
|
||||
}
|
||||
|
||||
// Draft proposal http://tc39.github.io/proposal-object-values-entries/#Object.values
|
||||
function ObjectValues(O) {
|
||||
// Steps 1-2.
|
||||
var object = ToObject(O);
|
||||
|
||||
// Steps 3-4.
|
||||
// EnumerableOwnProperties is inlined here.
|
||||
var keys = OwnPropertyKeys(object, JSITER_OWNONLY | JSITER_HIDDEN);
|
||||
var values = [];
|
||||
var valuesCount = 0;
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
if (!callFunction(std_Object_propertyIsEnumerable, object, key))
|
||||
continue;
|
||||
|
||||
var value = object[key];
|
||||
_DefineDataProperty(values, valuesCount++, value);
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
return values;
|
||||
}
|
||||
|
||||
// Draft proposal http://tc39.github.io/proposal-object-values-entries/#Object.entries
|
||||
function ObjectEntries(O) {
|
||||
// Steps 1-2.
|
||||
var object = ToObject(O);
|
||||
|
||||
// Steps 3-4.
|
||||
// EnumerableOwnProperties is inlined here.
|
||||
var keys = OwnPropertyKeys(object, JSITER_OWNONLY | JSITER_HIDDEN);
|
||||
var entries = [];
|
||||
var entriesCount = 0;
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
if (!callFunction(std_Object_propertyIsEnumerable, object, key))
|
||||
continue;
|
||||
|
||||
var value = object[key];
|
||||
_DefineDataProperty(entries, entriesCount++, [key, value]);
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
return entries;
|
||||
}
|
||||
|
@ -3671,6 +3671,20 @@ js::NewCopiedArrayForCallingAllocationSite(JSContext* cx, const Value* vp, size_
|
||||
return NewCopiedArrayTryUseGroup(cx, group, vp, length);
|
||||
}
|
||||
|
||||
bool
|
||||
js::NewValuePair(JSContext* cx, const Value& val1, const Value& val2, MutableHandleValue rval)
|
||||
{
|
||||
JS::AutoValueArray<2> vec(cx);
|
||||
vec[0].set(val1);
|
||||
vec[1].set(val2);
|
||||
|
||||
JSObject* aobj = js::NewDenseCopiedArray(cx, 2, vec.begin());
|
||||
if (!aobj)
|
||||
return false;
|
||||
rval.setObject(*aobj);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool
|
||||
js::ArrayInfo(JSContext* cx, unsigned argc, Value* vp)
|
||||
|
@ -123,6 +123,9 @@ extern JSObject*
|
||||
NewCopiedArrayForCallingAllocationSite(JSContext* cx, const Value* vp, size_t length,
|
||||
HandleObject proto = nullptr);
|
||||
|
||||
extern bool
|
||||
NewValuePair(JSContext* cx, const Value& val1, const Value& val2, MutableHandleValue rval);
|
||||
|
||||
/*
|
||||
* Determines whether a write to the given element on |obj| should fail because
|
||||
* |obj| is an Array with a non-writable length, and writing that element would
|
||||
|
@ -74,15 +74,7 @@ typedef HashSet<jsid, JsidHasher> IdSet;
|
||||
static inline bool
|
||||
NewKeyValuePair(JSContext* cx, jsid id, const Value& val, MutableHandleValue rval)
|
||||
{
|
||||
JS::AutoValueArray<2> vec(cx);
|
||||
vec[0].set(IdToValue(id));
|
||||
vec[1].set(val);
|
||||
|
||||
JSObject* aobj = NewDenseCopiedArray(cx, 2, vec.begin());
|
||||
if (!aobj)
|
||||
return false;
|
||||
rval.setObject(*aobj);
|
||||
return true;
|
||||
return NewValuePair(cx, IdToValue(id), val, rval);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
|
@ -3,7 +3,6 @@
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
if ("values" in Object) {
|
||||
assertEq(Object.values.length, 1);
|
||||
|
||||
var o, values;
|
||||
@ -88,7 +87,6 @@ if ("values" in Object) {
|
||||
assertEq(ownKeysCallCount, 1);
|
||||
assertDeepEq(values, [3, 1]);
|
||||
assertDeepEq(getOwnPropertyDescriptorCalls, ["c", "a"]);
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
Loading…
Reference in New Issue
Block a user