mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-09 17:44:56 +09:00
LibJS: Make Array.prototype.push() generic
This commit is contained in:
parent
9f7a6e116a
commit
4334a1b208
Notes:
sideshowbarker
2024-07-19 06:15:23 +09:00
Author: https://github.com/linusg
Commit: 4334a1b208
Pull-request: https://github.com/SerenityOS/serenity/pull/2328
4 changed files with 42 additions and 12 deletions
|
@ -168,13 +168,30 @@ Value ArrayPrototype::map(Interpreter& interpreter)
|
||||||
|
|
||||||
Value ArrayPrototype::push(Interpreter& interpreter)
|
Value ArrayPrototype::push(Interpreter& interpreter)
|
||||||
{
|
{
|
||||||
auto* array = array_from(interpreter);
|
auto* this_object = interpreter.this_value().to_object(interpreter);
|
||||||
if (!array)
|
if (!this_object)
|
||||||
return {};
|
return {};
|
||||||
|
if (this_object->is_array()) {
|
||||||
|
auto* array = static_cast<Array*>(this_object);
|
||||||
for (size_t i = 0; i < interpreter.argument_count(); ++i)
|
for (size_t i = 0; i < interpreter.argument_count(); ++i)
|
||||||
array->elements().append(interpreter.argument(i));
|
array->elements().append(interpreter.argument(i));
|
||||||
return Value(array->length());
|
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)
|
Value ArrayPrototype::unshift(Interpreter& interpreter)
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,9 +43,6 @@
|
||||||
#include <LibJS/Runtime/Value.h>
|
#include <LibJS/Runtime/Value.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
// 2 ** 53 - 1
|
|
||||||
#define MAX_ARRAY_LIKE_INDEX 9007199254740991.0
|
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
bool Value::is_array() const
|
bool Value::is_array() const
|
||||||
|
@ -261,7 +258,7 @@ i32 Value::as_i32() const
|
||||||
size_t Value::as_size_t() const
|
size_t Value::as_size_t() const
|
||||||
{
|
{
|
||||||
ASSERT(as_double() >= 0);
|
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
|
double Value::to_double(Interpreter& interpreter) const
|
||||||
|
|
|
@ -32,6 +32,9 @@
|
||||||
#include <LibJS/Forward.h>
|
#include <LibJS/Forward.h>
|
||||||
#include <LibJS/Runtime/Symbol.h>
|
#include <LibJS/Runtime/Symbol.h>
|
||||||
|
|
||||||
|
// 2 ** 53 - 1
|
||||||
|
static constexpr double MAX_ARRAY_LIKE_INDEX = 9007199254740991.0;
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
class Value {
|
class Value {
|
||||||
|
|
|
@ -1,11 +1,24 @@
|
||||||
load("test-common.js");
|
load("test-common.js");
|
||||||
|
|
||||||
try {
|
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" };
|
const o = { length: 5, 0: "foo", 1: "bar", 3: "baz" };
|
||||||
|
|
||||||
["every"].forEach(name => {
|
{
|
||||||
const visited = [];
|
const visited = [];
|
||||||
Array.prototype[name].call(o, function (value) {
|
Array.prototype.every.call(o, function (value) {
|
||||||
visited.push(value);
|
visited.push(value);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -13,7 +26,7 @@ try {
|
||||||
assert(visited[0] === "foo");
|
assert(visited[0] === "foo");
|
||||||
assert(visited[1] === "bar");
|
assert(visited[1] === "bar");
|
||||||
assert(visited[2] === "baz");
|
assert(visited[2] === "baz");
|
||||||
});
|
}
|
||||||
|
|
||||||
["find", "findIndex"].forEach(name => {
|
["find", "findIndex"].forEach(name => {
|
||||||
const visited = [];
|
const visited = [];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue