ref: 22a74771615f4c645ba27ad4b170235c96c02175
parent: 411b8b5b9c86be6a8f5c357f8f5606f1e9941669
author: Tor Andersson <tor@ccxvii.net>
date: Fri Feb 7 10:21:14 EST 2014
Implement ES5 array functions.
--- a/jsarray.c
+++ b/jsarray.c
@@ -419,6 +419,281 @@
return Ap_join(J, 0);
}
+static int Ap_indexOf(js_State *J, int argc)
+{
+ int k, len, from;
+
+ len = js_getlength(J, 0);
+ from = argc > 1 ? js_tointeger(J, 2) : 0;
+ if (from < 0) from = len + from;
+ if (from < 0) from = 0;
+
+ js_copy(J, 1);
+ for (k = from; k < len; ++k) {
+ if (js_hasindex(J, 0, k)) {
+ if (js_strictequal(J)) {
+ js_pushnumber(J, k);
+ return 1;
+ }
+ js_pop(J, 1);
+ }
+ }
+
+ js_pushnumber(J, -1);
+ return 1;
+}
+
+static int Ap_lastIndexOf(js_State *J, int argc)
+{
+ int k, len, from;
+
+ len = js_getlength(J, 0);
+ from = argc > 1 ? js_tointeger(J, 2) : len;
+ if (from > len - 1) from = len - 1;
+ if (from < 0) from = len + from;
+
+ js_copy(J, 1);
+ for (k = from; k >= 0; --k) {
+ if (js_hasindex(J, 0, k)) {
+ if (js_strictequal(J)) {
+ js_pushnumber(J, k);
+ return 1;
+ }
+ js_pop(J, 1);
+ }
+ }
+
+ js_pushnumber(J, -1);
+ return 1;
+}
+
+static int Ap_every(js_State *J, int argc)
+{
+ int k, len;
+
+ if (!js_iscallable(J, 1))
+ js_typeerror(J, "callback is not a function");
+
+ len = js_getlength(J, 0);
+ for (k = 0; k < len; ++k) {
+ if (js_hasindex(J, 0, k)) {
+ js_copy(J, 1);
+ if (argc > 1)
+ js_copy(J, 2);
+ else
+ js_pushundefined(J);
+ js_copy(J, -3);
+ js_pushnumber(J, k);
+ js_copy(J, 0);
+ js_call(J, 3);
+ if (!js_toboolean(J, -1))
+ return 1;
+ js_pop(J, 2);
+ }
+ }
+
+ js_pushboolean(J, 1);
+ return 1;
+}
+
+static int Ap_some(js_State *J, int argc)
+{
+ int k, len;
+
+ if (!js_iscallable(J, 1))
+ js_typeerror(J, "callback is not a function");
+
+ len = js_getlength(J, 0);
+ for (k = 0; k < len; ++k) {
+ if (js_hasindex(J, 0, k)) {
+ js_copy(J, 1);
+ if (argc > 1)
+ js_copy(J, 2);
+ else
+ js_pushundefined(J);
+ js_copy(J, -3);
+ js_pushnumber(J, k);
+ js_copy(J, 0);
+ js_call(J, 3);
+ if (js_toboolean(J, -1))
+ return 1;
+ js_pop(J, 2);
+ }
+ }
+
+ js_pushboolean(J, 0);
+ return 1;
+}
+
+static int Ap_forEach(js_State *J, int argc)
+{
+ int k, len;
+
+ if (!js_iscallable(J, 1))
+ js_typeerror(J, "callback is not a function");
+
+ len = js_getlength(J, 0);
+ for (k = 0; k < len; ++k) {
+ if (js_hasindex(J, 0, k)) {
+ js_copy(J, 1);
+ if (argc > 1)
+ js_copy(J, 2);
+ else
+ js_pushundefined(J);
+ js_copy(J, -3);
+ js_pushnumber(J, k);
+ js_copy(J, 0);
+ js_call(J, 3);
+ js_pop(J, 2);
+ }
+ }
+
+ return 0;
+}
+
+static int Ap_map(js_State *J, int argc)
+{
+ int k, len;
+
+ if (!js_iscallable(J, 1))
+ js_typeerror(J, "callback is not a function");
+
+ js_newarray(J);
+
+ len = js_getlength(J, 0);
+ for (k = 0; k < len; ++k) {
+ if (js_hasindex(J, 0, k)) {
+ js_copy(J, 1);
+ if (argc > 1)
+ js_copy(J, 2);
+ else
+ js_pushundefined(J);
+ js_copy(J, -3);
+ js_pushnumber(J, k);
+ js_copy(J, 0);
+ js_call(J, 3);
+ js_setindex(J, -3, k);
+ js_pop(J, 1);
+ }
+ }
+
+ return 1;
+}
+
+static int Ap_filter(js_State *J, int argc)
+{
+ int k, to, len;
+
+ if (!js_iscallable(J, 1))
+ js_typeerror(J, "callback is not a function");
+
+ js_newarray(J);
+ to = 0;
+
+ len = js_getlength(J, 0);
+ for (k = 0; k < len; ++k) {
+ if (js_hasindex(J, 0, k)) {
+ js_copy(J, 1);
+ if (argc > 1)
+ js_copy(J, 2);
+ else
+ js_pushundefined(J);
+ js_copy(J, -3);
+ js_pushnumber(J, k);
+ js_copy(J, 0);
+ js_call(J, 3);
+ if (js_toboolean(J, -1)) {
+ js_pop(J, 1);
+ js_setindex(J, -2, to++);
+ } else {
+ js_pop(J, 2);
+ }
+ }
+ }
+
+ return 1;
+}
+
+static int Ap_reduce(js_State *J, int argc)
+{
+ int k, len;
+
+ if (!js_iscallable(J, 1))
+ js_typeerror(J, "callback is not a function");
+
+ len = js_getlength(J, 0);
+ k = 0;
+
+ if (len == 0 && argc < 2)
+ js_typeerror(J, "no initial value");
+
+ /* initial value of accumulator */
+ if (argc >= 2)
+ js_copy(J, 2);
+ else {
+ while (k < len)
+ if (js_hasindex(J, 0, k++))
+ break;
+ if (k == len)
+ js_typeerror(J, "no initial value");
+ }
+
+ while (k < len) {
+ if (js_hasindex(J, 0, k)) {
+ js_copy(J, 1);
+ js_pushundefined(J);
+ js_rot(J, 4); /* accumulator on top */
+ js_rot(J, 4); /* property on top */
+ js_pushnumber(J, k);
+ js_copy(J, 0);
+ js_call(J, 4); /* calculate new accumulator */
+ }
+ ++k;
+ }
+
+ return 1; /* return accumulator */
+}
+
+static int Ap_reduceRight(js_State *J, int argc)
+{
+ int k, len;
+
+ if (!js_iscallable(J, 1))
+ js_typeerror(J, "callback is not a function");
+
+ len = js_getlength(J, 0);
+ k = len - 1;
+
+ if (len == 0 && argc < 2)
+ js_typeerror(J, "no initial value");
+
+ /* initial value of accumulator */
+ if (argc >= 2)
+ js_copy(J, 2);
+ else {
+ while (k >= 0)
+ if (js_hasindex(J, 0, k--))
+ break;
+ if (k < 0)
+ js_typeerror(J, "no initial value");
+ }
+
+ while (k >= 0) {
+ if (js_hasindex(J, 0, k)) {
+ js_copy(J, 1);
+ js_pushundefined(J);
+ js_rot(J, 4); /* accumulator on top */
+ js_rot(J, 4); /* property on top */
+ js_pushnumber(J, k);
+ js_copy(J, 0);
+ js_call(J, 4); /* calculate new accumulator */
+ }
+ --k;
+ }
+
+ return 1; /* return accumulator */
+}
+
static int A_isArray(js_State *J, int argc)
{
if (js_isobject(J, 1)) {
@@ -441,10 +716,21 @@
jsB_propf(J, "push", Ap_push, 1);
jsB_propf(J, "reverse", Ap_reverse, 0);
jsB_propf(J, "shift", Ap_shift, 0);
- jsB_propf(J, "slice", Ap_slice, 0);
+ jsB_propf(J, "slice", Ap_slice, 2);
jsB_propf(J, "sort", Ap_sort, 1);
- jsB_propf(J, "splice", Ap_splice, 0);
- jsB_propf(J, "unshift", Ap_unshift, 0);
+ jsB_propf(J, "splice", Ap_splice, 2);
+ jsB_propf(J, "unshift", Ap_unshift, 1);
+
+ /* ES5 */
+ jsB_propf(J, "indexOf", Ap_indexOf, 1);
+ jsB_propf(J, "lastIndexOf", Ap_lastIndexOf, 1);
+ jsB_propf(J, "every", Ap_every, 1);
+ jsB_propf(J, "some", Ap_some, 1);
+ jsB_propf(J, "forEach", Ap_forEach, 1);
+ jsB_propf(J, "map", Ap_map, 1);
+ jsB_propf(J, "filter", Ap_filter, 1);
+ jsB_propf(J, "reduce", Ap_reduce, 1);
+ jsB_propf(J, "reduceRight", Ap_reduceRight, 1);
}
js_newcconstructor(J, jsB_new_Array, jsB_new_Array, 1);
{