Commit aed5d734 authored by caitpotter88's avatar caitpotter88 Committed by Commit bot

Use proper ToLength() operation in %ArrayConcat()

LOG=N
R=dslomov@chromium.org
BUG=

Review URL: https://codereview.chromium.org/799853003

Cr-Commit-Position: refs/heads/master@{#25828}
parent 94071011
......@@ -1525,6 +1525,7 @@ void Genesis::InstallNativeFunctions() {
INSTALL_NATIVE(JSFunction, "ToInteger", to_integer_fun);
INSTALL_NATIVE(JSFunction, "ToUint32", to_uint32_fun);
INSTALL_NATIVE(JSFunction, "ToInt32", to_int32_fun);
INSTALL_NATIVE(JSFunction, "ToLength", to_length_fun);
INSTALL_NATIVE(JSFunction, "GlobalEval", global_eval_fun);
INSTALL_NATIVE(JSFunction, "Instantiate", instantiate_fun);
......
......@@ -98,6 +98,7 @@ enum BindingFlags {
V(TO_INTEGER_FUN_INDEX, JSFunction, to_integer_fun) \
V(TO_UINT32_FUN_INDEX, JSFunction, to_uint32_fun) \
V(TO_INT32_FUN_INDEX, JSFunction, to_int32_fun) \
V(TO_LENGTH_FUN_INDEX, JSFunction, to_length_fun) \
V(GLOBAL_EVAL_FUN_INDEX, JSFunction, global_eval_fun) \
V(INSTANTIATE_FUN_INDEX, JSFunction, instantiate_fun) \
V(CONFIGURE_INSTANCE_FUN_INDEX, JSFunction, configure_instance_fun) \
......@@ -416,6 +417,7 @@ class Context: public FixedArray {
ARRAY_VALUES_ITERATOR_INDEX,
SCRIPT_CONTEXT_TABLE_INDEX,
MAP_CACHE_INDEX,
TO_LENGTH_FUN_INDEX,
// Properties from here are treated as weak references by the full GC.
// Scavenge treats them as strong references.
......
......@@ -545,6 +545,12 @@ MaybeHandle<Object> Execution::ToInt32(
}
MaybeHandle<Object> Execution::ToLength(
Isolate* isolate, Handle<Object> obj) {
RETURN_NATIVE_CALL(to_length, { obj });
}
MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
Handle<Object> time_obj = isolate->factory()->NewNumber(time);
RETURN_NATIVE_CALL(create_date, { time_obj });
......
......@@ -69,6 +69,11 @@ class Execution FINAL : public AllStatic {
MUST_USE_RESULT static MaybeHandle<Object> ToUint32(
Isolate* isolate, Handle<Object> obj);
// ES6, draft 10-14-14, section 7.1.15
MUST_USE_RESULT static MaybeHandle<Object> ToLength(
Isolate* isolate, Handle<Object> obj);
// ECMA-262 9.8
MUST_USE_RESULT static MaybeHandle<Object> ToString(
Isolate* isolate, Handle<Object> obj);
......
......@@ -461,8 +461,12 @@ static bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
Handle<Object> key(isolate->heap()->length_string(), isolate);
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val,
Runtime::GetObjectProperty(isolate, receiver, key), false);
// TODO(caitp): implement ToLength() abstract operation for C++
val->ToUint32(&length);
// TODO(caitp): Support larger element indexes (up to 2^53-1).
if (!val->ToUint32(&length)) {
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val,
Execution::ToLength(isolate, val), false);
val->ToUint32(&length);
}
}
switch (receiver->GetElementsKind()) {
......
......@@ -40,6 +40,110 @@
})();
(function testConcatArrayLikeStringLength() {
"use strict";
var obj = {
"length": "6",
"1": "A",
"3": "B",
"5": "C"
};
obj[Symbol.isConcatSpreadable] = true;
var obj2 = { length: 3, "0": "0", "1": "1", "2": "2" };
var arr = ["X", "Y", "Z"];
assertEquals([void 0, "A", void 0, "B", void 0, "C",
{ "length": 3, "0": "0", "1": "1", "2": "2" },
"X", "Y", "Z"], Array.prototype.concat.call(obj, obj2, arr));
})();
(function testConcatArrayLikeNegativeLength() {
"use strict";
var obj = {
"length": -6,
"1": "A",
"3": "B",
"5": "C"
};
obj[Symbol.isConcatSpreadable] = true;
assertEquals([], [].concat(obj));
obj.length = -6.7;
assertEquals([], [].concat(obj));
obj.length = "-6";
assertEquals([], [].concat(obj));
})();
(function testConcatArrayLikeToLengthThrows() {
"use strict";
var obj = {
"length": {valueOf: null, toString: null},
"1": "A",
"3": "B",
"5": "C"
};
obj[Symbol.isConcatSpreadable] = true;
var obj2 = { length: 3, "0": "0", "1": "1", "2": "2" };
var arr = ["X", "Y", "Z"];
assertThrows(function() {
Array.prototype.concat.call(obj, obj2, arr);
}, TypeError);
})();
(function testConcatArrayLikePrimitiveNonNumberLength() {
"use strict";
var obj = {
"1": "A",
"3": "B",
"5": "C"
};
obj[Symbol.isConcatSpreadable] = true;
obj.length = {toString: function() { return "SIX"; }, valueOf: null };
assertEquals([], [].concat(obj));
obj.length = {toString: null, valueOf: function() { return "SIX"; } };
assertEquals([], [].concat(obj));
})();
(function testConcatArrayLikeLengthToStringThrows() {
"use strict";
function MyError() {}
var obj = {
"length": { toString: function() {
throw new MyError();
}, valueOf: null
},
"1": "A",
"3": "B",
"5": "C"
};
obj[Symbol.isConcatSpreadable] = true;
assertThrows(function() {
[].concat(obj);
}, MyError);
})();
(function testConcatArrayLikeLengthValueOfThrows() {
"use strict";
function MyError() {}
var obj = {
"length": { valueOf: function() {
throw new MyError();
}, toString: null
},
"1": "A",
"3": "B",
"5": "C"
};
obj[Symbol.isConcatSpreadable] = true;
assertThrows(function() {
[].concat(obj);
}, MyError);
})();
(function testConcatHoleyArray() {
"use strict";
var arr = [];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment