summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Libraries/LibJS/Runtime/ArrayPrototype.cpp41
-rw-r--r--Libraries/LibJS/Runtime/ArrayPrototype.h1
-rw-r--r--Libraries/LibJS/Tests/Array.prototype.slice.js53
3 files changed, 95 insertions, 0 deletions
diff --git a/Libraries/LibJS/Runtime/ArrayPrototype.cpp b/Libraries/LibJS/Runtime/ArrayPrototype.cpp
index 8ec1765fcd..d59c939128 100644
--- a/Libraries/LibJS/Runtime/ArrayPrototype.cpp
+++ b/Libraries/LibJS/Runtime/ArrayPrototype.cpp
@@ -51,6 +51,7 @@ ArrayPrototype::ArrayPrototype()
put_native_function("unshift", unshift, 1);
put_native_function("join", join, 1);
put_native_function("concat", concat, 1);
+ put_native_function("slice", slice, 2);
put("length", Value(0));
}
@@ -254,4 +255,44 @@ Value ArrayPrototype::concat(Interpreter& interpreter)
return Value(new_array);
}
+Value ArrayPrototype::slice(Interpreter& interpreter)
+{
+ auto* array = array_from(interpreter);
+ if (!array)
+ return {};
+
+ auto* new_array = Array::create(interpreter.global_object());
+ if (interpreter.argument_count() == 0) {
+ new_array->elements().append(array->elements());
+ return new_array;
+ }
+
+ ssize_t array_size = static_cast<ssize_t>(array->elements().size());
+ auto start_slice = interpreter.argument(0).to_i32();
+ auto end_slice = array_size;
+
+ if (start_slice > array_size)
+ return new_array;
+
+ if (start_slice < 0)
+ start_slice = end_slice + start_slice;
+
+ if (interpreter.argument_count() >= 2) {
+ end_slice = interpreter.argument(1).to_i32();
+
+ if (end_slice < 0)
+ end_slice = array_size + end_slice;
+ else if (end_slice > array_size)
+ end_slice = array_size;
+ }
+
+ size_t array_capacity = start_slice + array_size - end_slice;
+ new_array->elements().ensure_capacity(array_capacity);
+ for (ssize_t i = start_slice; i < end_slice; ++i) {
+ new_array->elements().append(array->elements().at(i));
+ }
+
+ return new_array;
+}
+
}
diff --git a/Libraries/LibJS/Runtime/ArrayPrototype.h b/Libraries/LibJS/Runtime/ArrayPrototype.h
index 2b9cfb89d1..5c27d3c9c7 100644
--- a/Libraries/LibJS/Runtime/ArrayPrototype.h
+++ b/Libraries/LibJS/Runtime/ArrayPrototype.h
@@ -49,6 +49,7 @@ private:
static Value unshift(Interpreter&);
static Value join(Interpreter&);
static Value concat(Interpreter&);
+ static Value slice(Interpreter&);
};
}
diff --git a/Libraries/LibJS/Tests/Array.prototype.slice.js b/Libraries/LibJS/Tests/Array.prototype.slice.js
new file mode 100644
index 0000000000..e34f2c1a1b
--- /dev/null
+++ b/Libraries/LibJS/Tests/Array.prototype.slice.js
@@ -0,0 +1,53 @@
+load("test-common.js");
+
+try {
+ assert(Array.prototype.slice.length === 2);
+
+ var array = ["hello", "friends", "serenity", 1];
+
+ var array_slice = array.slice();
+ assert(array_slice.length === array.length);
+ assert(array_slice.length === 4);
+ assert(array_slice[0] === "hello");
+ assert(array_slice[1] === "friends");
+ assert(array_slice[2] === "serenity");
+ assert(array_slice[3] === 1);
+
+ array_slice = array.slice(1)
+ assert(array_slice.length === 3);
+ assert(array_slice[0] === "friends");
+ assert(array_slice[1] === "serenity");
+ assert(array_slice[2] === 1);
+
+ array_slice = array.slice(0, 2);
+ assert(array_slice.length === 2);
+ assert(array_slice[0] === "hello");
+ assert(array_slice[1] === "friends");
+
+ array_slice = array.slice(-1);
+ assert(array_slice.length === 1);
+ assert(array_slice[0] === 1);
+
+ array_slice = array.slice(1, 1);
+ assert(array_slice.length === 0);
+
+ array_slice = array.slice(1, -1);
+ assert(array_slice.length === 2);
+ assert(array_slice[0] === "friends");
+ assert(array_slice[1] === "serenity");
+
+ array_slice = array.slice(2, -1);
+ assert(array_slice.length === 1);
+ assert(array_slice[0] === "serenity");
+
+ array_slice = array.slice(0, 100);
+ assert(array_slice.length === 4);
+ assert(array_slice[0] === "hello");
+ assert(array_slice[1] === "friends");
+ assert(array_slice[2] === "serenity");
+ assert(array_slice[3] === 1);
+
+ console.log("PASS");
+} catch (e) {
+ console.log("FAIL: " + e);
+}