diff options
Diffstat (limited to 'Libraries/LibJS')
-rw-r--r-- | Libraries/LibJS/Runtime/ArrayPrototype.cpp | 27 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/Value.cpp | 5 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/Value.h | 3 | ||||
-rw-r--r-- | Libraries/LibJS/Tests/Array.prototype-generic-functions.js | 19 |
4 files changed, 42 insertions, 12 deletions
diff --git a/Libraries/LibJS/Runtime/ArrayPrototype.cpp b/Libraries/LibJS/Runtime/ArrayPrototype.cpp index b9ff84a0ab..569463d537 100644 --- a/Libraries/LibJS/Runtime/ArrayPrototype.cpp +++ b/Libraries/LibJS/Runtime/ArrayPrototype.cpp @@ -168,12 +168,29 @@ Value ArrayPrototype::map(Interpreter& interpreter) Value ArrayPrototype::push(Interpreter& interpreter) { - auto* array = array_from(interpreter); - if (!array) + auto* this_object = interpreter.this_value().to_object(interpreter); + if (!this_object) return {}; - for (size_t i = 0; i < interpreter.argument_count(); ++i) - array->elements().append(interpreter.argument(i)); - return Value(array->length()); + if (this_object->is_array()) { + auto* array = static_cast<Array*>(this_object); + for (size_t i = 0; i < interpreter.argument_count(); ++i) + array->elements().append(interpreter.argument(i)); + return Value(array->length()); + } + auto length = get_length(interpreter, *this_object); + if (interpreter.exception()) + return {}; + auto argument_count = interpreter.argument_count(); + auto new_length = length + argument_count; + if (new_length > MAX_ARRAY_LIKE_INDEX) + return interpreter.throw_exception<TypeError>("Maximum array size exceeded"); + for (size_t i = 0; i < argument_count; ++i) + this_object->put_by_index(length + i, interpreter.argument(i)); + auto new_length_value = Value((i32)new_length); + this_object->put("length", new_length_value); + if (interpreter.exception()) + return {}; + return new_length_value; } Value ArrayPrototype::unshift(Interpreter& interpreter) diff --git a/Libraries/LibJS/Runtime/Value.cpp b/Libraries/LibJS/Runtime/Value.cpp index dc45ea589b..80917df5d5 100644 --- a/Libraries/LibJS/Runtime/Value.cpp +++ b/Libraries/LibJS/Runtime/Value.cpp @@ -43,9 +43,6 @@ #include <LibJS/Runtime/Value.h> #include <math.h> -// 2 ** 53 - 1 -#define MAX_ARRAY_LIKE_INDEX 9007199254740991.0 - namespace JS { bool Value::is_array() const @@ -261,7 +258,7 @@ i32 Value::as_i32() const size_t Value::as_size_t() const { ASSERT(as_double() >= 0); - return min((double)(i32)as_double(), MAX_ARRAY_LIKE_INDEX); + return min((double)as_i32(), MAX_ARRAY_LIKE_INDEX); } double Value::to_double(Interpreter& interpreter) const diff --git a/Libraries/LibJS/Runtime/Value.h b/Libraries/LibJS/Runtime/Value.h index aa6f690a49..887a11ebcf 100644 --- a/Libraries/LibJS/Runtime/Value.h +++ b/Libraries/LibJS/Runtime/Value.h @@ -32,6 +32,9 @@ #include <LibJS/Forward.h> #include <LibJS/Runtime/Symbol.h> +// 2 ** 53 - 1 +static constexpr double MAX_ARRAY_LIKE_INDEX = 9007199254740991.0; + namespace JS { class Value { diff --git a/Libraries/LibJS/Tests/Array.prototype-generic-functions.js b/Libraries/LibJS/Tests/Array.prototype-generic-functions.js index 63d19532eb..d906d2be3b 100644 --- a/Libraries/LibJS/Tests/Array.prototype-generic-functions.js +++ b/Libraries/LibJS/Tests/Array.prototype-generic-functions.js @@ -1,11 +1,24 @@ load("test-common.js"); try { + [undefined, "foo", -42, 0].forEach(length => { + const o = { length }; + + assert(Array.prototype.push.call(o, "foo") === 1); + assert(o.length === 1); + assert(o[0] === "foo"); + assert(Array.prototype.push.call(o, "bar", "baz") === 3); + assert(o.length === 3); + assert(o[0] === "foo"); + assert(o[1] === "bar"); + assert(o[2] === "baz"); + }); + const o = { length: 5, 0: "foo", 1: "bar", 3: "baz" }; - ["every"].forEach(name => { + { const visited = []; - Array.prototype[name].call(o, function (value) { + Array.prototype.every.call(o, function (value) { visited.push(value); return true; }); @@ -13,7 +26,7 @@ try { assert(visited[0] === "foo"); assert(visited[1] === "bar"); assert(visited[2] === "baz"); - }); + } ["find", "findIndex"].forEach(name => { const visited = []; |