Coverage Report

Created: 2026-06-08 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mupdf/thirdparty/mujs/jsarray.c
Line
Count
Source
1
#include "jsi.h"
2
3
#ifndef JS_HEAPSORT
4
#define JS_HEAPSORT 0
5
#endif
6
7
int js_getlength(js_State *J, int idx)
8
0
{
9
0
  int len;
10
0
  js_getproperty(J, idx, "length");
11
0
  len = js_tointeger(J, -1);
12
0
  js_pop(J, 1);
13
0
  return len;
14
0
}
15
16
void js_setlength(js_State *J, int idx, int len)
17
0
{
18
0
  js_pushnumber(J, len);
19
0
  js_setproperty(J, idx < 0 ? idx - 1 : idx, "length");
20
0
}
21
22
static void jsB_new_Array(js_State *J)
23
0
{
24
0
  int i, top = js_gettop(J);
25
26
0
  js_newarray(J);
27
28
0
  if (top == 2) {
29
0
    if (js_isnumber(J, 1)) {
30
0
      js_copy(J, 1);
31
0
      js_setproperty(J, -2, "length");
32
0
    } else {
33
0
      js_copy(J, 1);
34
0
      js_setindex(J, -2, 0);
35
0
    }
36
0
  } else {
37
0
    for (i = 1; i < top; ++i) {
38
0
      js_copy(J, i);
39
0
      js_setindex(J, -2, i - 1);
40
0
    }
41
0
  }
42
0
}
43
44
static void Ap_concat(js_State *J)
45
0
{
46
0
  int i, top = js_gettop(J);
47
0
  int n, k, len;
48
49
0
  js_newarray(J);
50
0
  n = 0;
51
52
0
  for (i = 0; i < top; ++i) {
53
0
    js_copy(J, i);
54
0
    if (js_isarray(J, -1)) {
55
0
      len = js_getlength(J, -1);
56
0
      for (k = 0; k < len; ++k)
57
0
        if (js_hasindex(J, -1, k))
58
0
          js_setindex(J, -3, n++);
59
0
      js_pop(J, 1);
60
0
    } else {
61
0
      js_setindex(J, -2, n++);
62
0
    }
63
0
  }
64
0
}
65
66
/* ugly cycle detection for Array.prototype.join */
67
static void Ap_join(js_State *J);
68
static void Ap_toString(js_State *J);
69
static int Ap_join_cycle(js_State *J)
70
0
{
71
0
  js_Object *needle = js_toobject(J, 0);
72
0
  int top = J->tracetop - 1;
73
0
  while (top > 0) {
74
0
    int stk = J->trace[top].stack;
75
0
    js_Value *fun = &J->stack[stk-1];
76
0
    if (fun->t.type != JS_TOBJECT) return 0;
77
0
    if (fun->u.object->type != JS_CCFUNCTION) return 0;
78
0
    if (fun->u.object->u.c.function == Ap_join)
79
0
    {
80
0
      js_Value *obj = &J->stack[stk];
81
0
      if (obj->t.type != JS_TOBJECT) return 0;
82
0
      if (obj->u.object == needle)
83
0
        return 1;
84
0
    }
85
0
    else if (fun->u.object->u.c.function == Ap_toString)
86
0
    {
87
      /* join calls toString which calls join which calls toString, etc */
88
0
    }
89
0
    else
90
0
    {
91
0
      return 0;
92
0
    }
93
0
    --top;
94
0
  }
95
0
  return 0;
96
0
}
97
98
static void Ap_join(js_State *J)
99
0
{
100
0
  char * volatile out = NULL;
101
0
  const char * volatile r = NULL;
102
0
  const char *sep;
103
0
  int seplen;
104
0
  int k, n, len, rlen;
105
106
0
  if (Ap_join_cycle(J)) {
107
0
    js_pushliteral(J, "");
108
0
    return;
109
0
  }
110
111
0
  len = js_getlength(J, 0);
112
113
0
  if (js_isdefined(J, 1)) {
114
0
    sep = js_tostring(J, 1);
115
0
    seplen = strlen(sep);
116
0
  } else {
117
0
    sep = ",";
118
0
    seplen = 1;
119
0
  }
120
121
0
  if (len <= 0) {
122
0
    js_pushliteral(J, "");
123
0
    return;
124
0
  }
125
126
0
  if (js_try(J)) {
127
0
    js_free(J, out);
128
0
    js_throw(J);
129
0
  }
130
131
0
  n = 0;
132
0
  for (k = 0; k < len; ++k) {
133
0
    js_getindex(J, 0, k);
134
0
    if (js_iscoercible(J, -1)) {
135
0
      r = js_tostring(J, -1);
136
0
      rlen = strlen(r);
137
0
    } else {
138
0
      rlen = 0;
139
0
    }
140
141
0
    if (k == 0) {
142
0
      out = js_malloc(J, rlen + 1);
143
0
      if (rlen > 0) {
144
0
        memcpy(out, r, rlen);
145
0
        n += rlen;
146
0
      }
147
0
    } else {
148
0
      if (n + seplen + rlen > JS_STRLIMIT)
149
0
        js_rangeerror(J, "invalid string length");
150
0
      out = js_realloc(J, out, n + seplen + rlen + 1);
151
0
      if (seplen > 0) {
152
0
        memcpy(out + n, sep, seplen);
153
0
        n += seplen;
154
0
      }
155
0
      if (rlen > 0) {
156
0
        memcpy(out + n, r, rlen);
157
0
        n += rlen;
158
0
      }
159
0
    }
160
161
0
    js_pop(J, 1);
162
0
  }
163
164
0
  js_pushlstring(J, out, n);
165
0
  js_endtry(J);
166
0
  js_free(J, out);
167
0
}
168
169
static void Ap_pop(js_State *J)
170
0
{
171
0
  int n;
172
173
0
  n = js_getlength(J, 0);
174
175
0
  if (n > 0) {
176
0
    js_getindex(J, 0, n - 1);
177
0
    js_delindex(J, 0, n - 1);
178
0
    js_setlength(J, 0, n - 1);
179
0
  } else {
180
0
    js_setlength(J, 0, 0);
181
0
    js_pushundefined(J);
182
0
  }
183
0
}
184
185
static void Ap_push(js_State *J)
186
0
{
187
0
  int i, top = js_gettop(J);
188
0
  int n;
189
190
0
  n = js_getlength(J, 0);
191
192
0
  for (i = 1; i < top; ++i, ++n) {
193
0
    js_copy(J, i);
194
0
    js_setindex(J, 0, n);
195
0
  }
196
197
0
  js_setlength(J, 0, n);
198
199
0
  js_pushnumber(J, n);
200
0
}
201
202
static void Ap_reverse(js_State *J)
203
0
{
204
0
  int len, middle, lower;
205
206
0
  len = js_getlength(J, 0);
207
0
  middle = len / 2;
208
0
  lower = 0;
209
210
0
  while (lower != middle) {
211
0
    int upper = len - lower - 1;
212
0
    int haslower = js_hasindex(J, 0, lower);
213
0
    int hasupper = js_hasindex(J, 0, upper);
214
0
    if (haslower && hasupper) {
215
0
      js_setindex(J, 0, lower);
216
0
      js_setindex(J, 0, upper);
217
0
    } else if (hasupper) {
218
0
      js_setindex(J, 0, lower);
219
0
      js_delindex(J, 0, upper);
220
0
    } else if (haslower) {
221
0
      js_setindex(J, 0, upper);
222
0
      js_delindex(J, 0, lower);
223
0
    }
224
0
    ++lower;
225
0
  }
226
227
0
  js_copy(J, 0);
228
0
}
229
230
static void Ap_shift(js_State *J)
231
0
{
232
0
  int k, len;
233
234
0
  len = js_getlength(J, 0);
235
236
0
  if (len == 0) {
237
0
    js_setlength(J, 0, 0);
238
0
    js_pushundefined(J);
239
0
    return;
240
0
  }
241
242
0
  js_getindex(J, 0, 0);
243
244
0
  for (k = 1; k < len; ++k) {
245
0
    if (js_hasindex(J, 0, k))
246
0
      js_setindex(J, 0, k - 1);
247
0
    else
248
0
      js_delindex(J, 0, k - 1);
249
0
  }
250
251
0
  js_delindex(J, 0, len - 1);
252
0
  js_setlength(J, 0, len - 1);
253
0
}
254
255
static void Ap_slice(js_State *J)
256
0
{
257
0
  int len, s, e, n;
258
0
  double sv, ev;
259
260
0
  js_newarray(J);
261
262
0
  len = js_getlength(J, 0);
263
0
  sv = js_tointeger(J, 1);
264
0
  ev = js_isdefined(J, 2) ? js_tointeger(J, 2) : len;
265
266
0
  if (sv < 0) sv = sv + len;
267
0
  if (ev < 0) ev = ev + len;
268
269
0
  s = sv < 0 ? 0 : sv > len ? len : sv;
270
0
  e = ev < 0 ? 0 : ev > len ? len : ev;
271
272
0
  for (n = 0; s < e; ++s, ++n)
273
0
    if (js_hasindex(J, 0, s))
274
0
      js_setindex(J, -2, n);
275
0
}
276
277
static int Ap_sort_cmp(js_State *J, int idx_a, int idx_b)
278
0
{
279
0
  js_Object *obj = js_tovalue(J, 0)->u.object;
280
0
  if (obj->u.a.simple && idx_b < obj->u.a.flat_length) {
281
0
    js_Value *val_a = &obj->u.a.array[idx_a];
282
0
    js_Value *val_b = &obj->u.a.array[idx_b];
283
0
    int und_a = val_a->t.type == JS_TUNDEFINED;
284
0
    int und_b = val_b->t.type == JS_TUNDEFINED;
285
0
    if (und_a) return und_b;
286
0
    if (und_b) return -1;
287
0
    if (js_iscallable(J, 1)) {
288
0
      double v;
289
0
      js_copy(J, 1); /* copy function */
290
0
      js_pushundefined(J); /* no 'this' binding */
291
0
      js_pushvalue(J, *val_a);
292
0
      js_pushvalue(J, *val_b);
293
0
      js_call(J, 2);
294
0
      v = js_tonumber(J, -1);
295
0
      js_pop(J, 1);
296
0
      if (isnan(v))
297
0
        return 0;
298
0
      if (v == 0)
299
0
        return 0;
300
0
      return v < 0 ? -1 : 1;
301
0
    } else {
302
0
      const char *str_a, *str_b;
303
0
      int c;
304
0
      js_pushvalue(J, *val_a);
305
0
      js_pushvalue(J, *val_b);
306
0
      str_a = js_tostring(J, -2);
307
0
      str_b = js_tostring(J, -1);
308
0
      c = strcmp(str_a, str_b);
309
0
      js_pop(J, 2);
310
0
      return c;
311
0
    }
312
0
  } else {
313
0
    int und_a, und_b;
314
0
    int has_a = js_hasindex(J, 0, idx_a);
315
0
    int has_b = js_hasindex(J, 0, idx_b);
316
0
    if (!has_a && !has_b) {
317
0
      return 0;
318
0
    }
319
0
    if (has_a && !has_b) {
320
0
      js_pop(J, 1);
321
0
      return -1;
322
0
    }
323
0
    if (!has_a && has_b) {
324
0
      js_pop(J, 1);
325
0
      return 1;
326
0
    }
327
328
0
    und_a = js_isundefined(J, -2);
329
0
    und_b = js_isundefined(J, -1);
330
0
    if (und_a) {
331
0
      js_pop(J, 2);
332
0
      return und_b;
333
0
    }
334
0
    if (und_b) {
335
0
      js_pop(J, 2);
336
0
      return -1;
337
0
    }
338
339
0
    if (js_iscallable(J, 1)) {
340
0
      double v;
341
0
      js_copy(J, 1); /* copy function */
342
0
      js_pushundefined(J); /* no 'this' binding */
343
0
      js_copy(J, -4);
344
0
      js_copy(J, -4);
345
0
      js_call(J, 2);
346
0
      v = js_tonumber(J, -1);
347
0
      js_pop(J, 3);
348
0
      if (isnan(v))
349
0
        return 0;
350
0
      if (v == 0)
351
0
        return 0;
352
0
      return v < 0 ? -1 : 1;
353
0
    } else {
354
0
      const char *str_a = js_tostring(J, -2);
355
0
      const char *str_b = js_tostring(J, -1);
356
0
      int c = strcmp(str_a, str_b);
357
0
      js_pop(J, 2);
358
0
      return c;
359
0
    }
360
0
  }
361
0
}
362
363
static void Ap_sort_swap(js_State *J, int idx_a, int idx_b)
364
0
{
365
0
  js_Object *obj = js_tovalue(J, 0)->u.object;
366
0
  if (obj->u.a.simple && idx_b < obj->u.a.flat_length) {
367
0
    js_Value tmp = obj->u.a.array[idx_a];
368
0
    obj->u.a.array[idx_a] = obj->u.a.array[idx_b];
369
0
    obj->u.a.array[idx_b] = tmp;
370
0
  } else {
371
0
    int has_a = js_hasindex(J, 0, idx_a);
372
0
    int has_b = js_hasindex(J, 0, idx_b);
373
0
    if (has_a && has_b) {
374
0
      js_setindex(J, 0, idx_a);
375
0
      js_setindex(J, 0, idx_b);
376
0
    } else if (has_a && !has_b) {
377
0
      js_delindex(J, 0, idx_a);
378
0
      js_setindex(J, 0, idx_b);
379
0
    } else if (!has_a && has_b) {
380
0
      js_delindex(J, 0, idx_b);
381
0
      js_setindex(J, 0, idx_a);
382
0
    }
383
0
  }
384
0
}
385
386
/* A bottom-up/bouncing heapsort implementation */
387
388
static int Ap_sort_leaf(js_State *J, int i, int end)
389
0
{
390
0
  int j = i;
391
0
  int lc = (j << 1) + 1; /* left child */
392
0
  int rc = (j << 1) + 2; /* right child */
393
0
  while (rc < end) {
394
0
    if (Ap_sort_cmp(J, lc, rc) <= 0)
395
0
      j = rc;
396
0
    else
397
0
      j = lc;
398
0
    lc = (j << 1) + 1;
399
0
    rc = (j << 1) + 2;
400
0
  }
401
0
  if (lc < end)
402
0
    j = lc;
403
0
  return j;
404
0
}
405
406
static void Ap_sort_sift(js_State *J, int i, int end)
407
0
{
408
0
  int j = Ap_sort_leaf(J, i, end);
409
0
  while (j > i && Ap_sort_cmp(J, i, j) > 0) {
410
0
    j = (j - 1) >> 1; /* parent */
411
0
  }
412
0
  while (j > i) {
413
0
    Ap_sort_swap(J, i, j);
414
0
    j = (j - 1) >> 1; /* parent */
415
0
  }
416
0
}
417
418
static void Ap_sort_heapsort(js_State *J, int n)
419
0
{
420
0
  int i;
421
0
  for (i = n / 2 - 1; i >= 0; --i)
422
0
    Ap_sort_sift(J, i, n);
423
0
  for (i = n - 1; i > 0; --i) {
424
0
    Ap_sort_swap(J, 0, i);
425
0
    Ap_sort_sift(J, 0, i);
426
0
  }
427
0
}
428
429
static void Ap_sort(js_State *J)
430
0
{
431
0
  int len;
432
433
0
  len = js_getlength(J, 0);
434
0
  if (len <= 1) {
435
0
    js_copy(J, 0);
436
0
    return;
437
0
  }
438
439
0
  if (!js_iscallable(J, 1) && !js_isundefined(J, 1))
440
0
    js_typeerror(J, "comparison function must be a function or undefined");
441
442
0
  if (len >= INT_MAX)
443
0
    js_rangeerror(J, "array is too large to sort");
444
445
0
  Ap_sort_heapsort(J, len);
446
447
0
  js_copy(J, 0);
448
0
}
449
450
static void Ap_splice(js_State *J)
451
0
{
452
0
  int top = js_gettop(J);
453
0
  int len, start, del, add, k;
454
455
0
  len = js_getlength(J, 0);
456
0
  start = js_tointeger(J, 1);
457
0
  if (start < 0)
458
0
    start = (len + start) > 0 ? len + start : 0;
459
0
  else if (start > len)
460
0
    start = len;
461
462
0
  if (js_isdefined(J, 2))
463
0
    del = js_tointeger(J, 2);
464
0
  else
465
0
    del = len - start;
466
0
  if (del > len - start)
467
0
    del = len - start;
468
0
  if (del < 0)
469
0
    del = 0;
470
471
0
  js_newarray(J);
472
473
  /* copy deleted items to return array */
474
0
  for (k = 0; k < del; ++k)
475
0
    if (js_hasindex(J, 0, start + k))
476
0
      js_setindex(J, -2, k);
477
0
  js_setlength(J, -1, del);
478
479
  /* shift the tail to resize the hole left by deleted items */
480
0
  add = top - 3;
481
0
  if (add < del) {
482
0
    for (k = start; k < len - del; ++k) {
483
0
      if (js_hasindex(J, 0, k + del))
484
0
        js_setindex(J, 0, k + add);
485
0
      else
486
0
        js_delindex(J, 0, k + add);
487
0
    }
488
0
    for (k = len; k > len - del + add; --k)
489
0
      js_delindex(J, 0, k - 1);
490
0
  } else if (add > del) {
491
0
    for (k = len - del; k > start; --k) {
492
0
      if (js_hasindex(J, 0, k + del - 1))
493
0
        js_setindex(J, 0, k + add - 1);
494
0
      else
495
0
        js_delindex(J, 0, k + add - 1);
496
0
    }
497
0
  }
498
499
  /* copy new items into the hole */
500
0
  for (k = 0; k < add; ++k) {
501
0
    js_copy(J, 3 + k);
502
0
    js_setindex(J, 0, start + k);
503
0
  }
504
505
0
  js_setlength(J, 0, len - del + add);
506
0
}
507
508
static void Ap_unshift(js_State *J)
509
0
{
510
0
  int i, top = js_gettop(J);
511
0
  int k, len;
512
513
0
  len = js_getlength(J, 0);
514
515
0
  for (k = len; k > 0; --k) {
516
0
    int from = k - 1;
517
0
    int to = k + top - 2;
518
0
    if (js_hasindex(J, 0, from))
519
0
      js_setindex(J, 0, to);
520
0
    else
521
0
      js_delindex(J, 0, to);
522
0
  }
523
524
0
  for (i = 1; i < top; ++i) {
525
0
    js_copy(J, i);
526
0
    js_setindex(J, 0, i - 1);
527
0
  }
528
529
0
  js_setlength(J, 0, len + top - 1);
530
531
0
  js_pushnumber(J, len + top - 1);
532
0
}
533
534
static void Ap_toString(js_State *J)
535
0
{
536
0
  if (!js_iscoercible(J, 0))
537
0
    js_typeerror(J, "'this' is not an object");
538
0
  js_getproperty(J, 0, "join");
539
0
  if (!js_iscallable(J, -1)) {
540
0
    js_pop(J, 1);
541
    /* TODO: call Object.prototype.toString implementation directly */
542
0
    js_getglobal(J, "Object");
543
0
    js_getproperty(J, -1, "prototype");
544
0
    js_rot2pop1(J);
545
0
    js_getproperty(J, -1, "toString");
546
0
    js_rot2pop1(J);
547
0
  }
548
0
  js_copy(J, 0);
549
0
  js_call(J, 0);
550
0
}
551
552
static void Ap_indexOf(js_State *J)
553
0
{
554
0
  int k, len, from;
555
556
0
  len = js_getlength(J, 0);
557
0
  from = js_isdefined(J, 2) ? js_tointeger(J, 2) : 0;
558
0
  if (from < 0) from = len + from;
559
0
  if (from < 0) from = 0;
560
561
0
  js_copy(J, 1);
562
0
  for (k = from; k < len; ++k) {
563
0
    if (js_hasindex(J, 0, k)) {
564
0
      if (js_strictequal(J)) {
565
0
        js_pushnumber(J, k);
566
0
        return;
567
0
      }
568
0
      js_pop(J, 1);
569
0
    }
570
0
  }
571
572
0
  js_pushnumber(J, -1);
573
0
}
574
575
static void Ap_lastIndexOf(js_State *J)
576
0
{
577
0
  int k, len, from;
578
579
0
  len = js_getlength(J, 0);
580
0
  from = js_isdefined(J, 2) ? js_tointeger(J, 2) : len - 1;
581
0
  if (from > len - 1) from = len - 1;
582
0
  if (from < 0) from = len + from;
583
584
0
  js_copy(J, 1);
585
0
  for (k = from; k >= 0; --k) {
586
0
    if (js_hasindex(J, 0, k)) {
587
0
      if (js_strictequal(J)) {
588
0
        js_pushnumber(J, k);
589
0
        return;
590
0
      }
591
0
      js_pop(J, 1);
592
0
    }
593
0
  }
594
595
0
  js_pushnumber(J, -1);
596
0
}
597
598
static void Ap_every(js_State *J)
599
0
{
600
0
  int hasthis = js_gettop(J) >= 3;
601
0
  int k, len;
602
603
0
  if (!js_iscallable(J, 1))
604
0
    js_typeerror(J, "callback is not a function");
605
606
0
  len = js_getlength(J, 0);
607
0
  for (k = 0; k < len; ++k) {
608
0
    if (js_hasindex(J, 0, k)) {
609
0
      js_copy(J, 1);
610
0
      if (hasthis)
611
0
        js_copy(J, 2);
612
0
      else
613
0
        js_pushundefined(J);
614
0
      js_copy(J, -3);
615
0
      js_pushnumber(J, k);
616
0
      js_copy(J, 0);
617
0
      js_call(J, 3);
618
0
      if (!js_toboolean(J, -1))
619
0
        return;
620
0
      js_pop(J, 2);
621
0
    }
622
0
  }
623
624
0
  js_pushboolean(J, 1);
625
0
}
626
627
static void Ap_some(js_State *J)
628
0
{
629
0
  int hasthis = js_gettop(J) >= 3;
630
0
  int k, len;
631
632
0
  if (!js_iscallable(J, 1))
633
0
    js_typeerror(J, "callback is not a function");
634
635
0
  len = js_getlength(J, 0);
636
0
  for (k = 0; k < len; ++k) {
637
0
    if (js_hasindex(J, 0, k)) {
638
0
      js_copy(J, 1);
639
0
      if (hasthis)
640
0
        js_copy(J, 2);
641
0
      else
642
0
        js_pushundefined(J);
643
0
      js_copy(J, -3);
644
0
      js_pushnumber(J, k);
645
0
      js_copy(J, 0);
646
0
      js_call(J, 3);
647
0
      if (js_toboolean(J, -1))
648
0
        return;
649
0
      js_pop(J, 2);
650
0
    }
651
0
  }
652
653
0
  js_pushboolean(J, 0);
654
0
}
655
656
static void Ap_forEach(js_State *J)
657
0
{
658
0
  int hasthis = js_gettop(J) >= 3;
659
0
  int k, len;
660
661
0
  if (!js_iscallable(J, 1))
662
0
    js_typeerror(J, "callback is not a function");
663
664
0
  len = js_getlength(J, 0);
665
0
  for (k = 0; k < len; ++k) {
666
0
    if (js_hasindex(J, 0, k)) {
667
0
      js_copy(J, 1);
668
0
      if (hasthis)
669
0
        js_copy(J, 2);
670
0
      else
671
0
        js_pushundefined(J);
672
0
      js_copy(J, -3);
673
0
      js_pushnumber(J, k);
674
0
      js_copy(J, 0);
675
0
      js_call(J, 3);
676
0
      js_pop(J, 2);
677
0
    }
678
0
  }
679
680
0
  js_pushundefined(J);
681
0
}
682
683
static void Ap_map(js_State *J)
684
0
{
685
0
  int hasthis = js_gettop(J) >= 3;
686
0
  int k, len;
687
688
0
  if (!js_iscallable(J, 1))
689
0
    js_typeerror(J, "callback is not a function");
690
691
0
  js_newarray(J);
692
693
0
  len = js_getlength(J, 0);
694
0
  for (k = 0; k < len; ++k) {
695
0
    if (js_hasindex(J, 0, k)) {
696
0
      js_copy(J, 1);
697
0
      if (hasthis)
698
0
        js_copy(J, 2);
699
0
      else
700
0
        js_pushundefined(J);
701
0
      js_copy(J, -3);
702
0
      js_pushnumber(J, k);
703
0
      js_copy(J, 0);
704
0
      js_call(J, 3);
705
0
      js_setindex(J, -3, k);
706
0
      js_pop(J, 1);
707
0
    }
708
0
  }
709
0
  js_setlength(J, -1, len);
710
0
}
711
712
static void Ap_filter(js_State *J)
713
0
{
714
0
  int hasthis = js_gettop(J) >= 3;
715
0
  int k, to, len;
716
717
0
  if (!js_iscallable(J, 1))
718
0
    js_typeerror(J, "callback is not a function");
719
720
0
  js_newarray(J);
721
0
  to = 0;
722
723
0
  len = js_getlength(J, 0);
724
0
  for (k = 0; k < len; ++k) {
725
0
    if (js_hasindex(J, 0, k)) {
726
0
      js_copy(J, 1);
727
0
      if (hasthis)
728
0
        js_copy(J, 2);
729
0
      else
730
0
        js_pushundefined(J);
731
0
      js_copy(J, -3);
732
0
      js_pushnumber(J, k);
733
0
      js_copy(J, 0);
734
0
      js_call(J, 3);
735
0
      if (js_toboolean(J, -1)) {
736
0
        js_pop(J, 1);
737
0
        js_setindex(J, -2, to++);
738
0
      } else {
739
0
        js_pop(J, 2);
740
0
      }
741
0
    }
742
0
  }
743
0
}
744
745
static void Ap_reduce(js_State *J)
746
0
{
747
0
  int hasinitial = js_gettop(J) >= 3;
748
0
  int k, len;
749
750
0
  if (!js_iscallable(J, 1))
751
0
    js_typeerror(J, "callback is not a function");
752
753
0
  len = js_getlength(J, 0);
754
0
  k = 0;
755
756
0
  if (len == 0 && !hasinitial)
757
0
    js_typeerror(J, "no initial value");
758
759
  /* initial value of accumulator */
760
0
  if (hasinitial)
761
0
    js_copy(J, 2);
762
0
  else {
763
0
    while (k < len)
764
0
      if (js_hasindex(J, 0, k++))
765
0
        break;
766
0
    if (k == len)
767
0
      js_typeerror(J, "no initial value");
768
0
  }
769
770
0
  while (k < len) {
771
0
    if (js_hasindex(J, 0, k)) {
772
0
      js_copy(J, 1);
773
0
      js_pushundefined(J);
774
0
      js_rot(J, 4); /* accumulator on top */
775
0
      js_rot(J, 4); /* property on top */
776
0
      js_pushnumber(J, k);
777
0
      js_copy(J, 0);
778
0
      js_call(J, 4); /* calculate new accumulator */
779
0
    }
780
0
    ++k;
781
0
  }
782
783
  /* return accumulator */
784
0
}
785
786
static void Ap_reduceRight(js_State *J)
787
0
{
788
0
  int hasinitial = js_gettop(J) >= 3;
789
0
  int k, len;
790
791
0
  if (!js_iscallable(J, 1))
792
0
    js_typeerror(J, "callback is not a function");
793
794
0
  len = js_getlength(J, 0);
795
0
  k = len - 1;
796
797
0
  if (len == 0 && !hasinitial)
798
0
    js_typeerror(J, "no initial value");
799
800
  /* initial value of accumulator */
801
0
  if (hasinitial)
802
0
    js_copy(J, 2);
803
0
  else {
804
0
    while (k >= 0)
805
0
      if (js_hasindex(J, 0, k--))
806
0
        break;
807
0
    if (k < 0)
808
0
      js_typeerror(J, "no initial value");
809
0
  }
810
811
0
  while (k >= 0) {
812
0
    if (js_hasindex(J, 0, k)) {
813
0
      js_copy(J, 1);
814
0
      js_pushundefined(J);
815
0
      js_rot(J, 4); /* accumulator on top */
816
0
      js_rot(J, 4); /* property on top */
817
0
      js_pushnumber(J, k);
818
0
      js_copy(J, 0);
819
0
      js_call(J, 4); /* calculate new accumulator */
820
0
    }
821
0
    --k;
822
0
  }
823
824
  /* return accumulator */
825
0
}
826
827
static void A_isArray(js_State *J)
828
0
{
829
0
  if (js_isobject(J, 1)) {
830
0
    js_Object *T = js_toobject(J, 1);
831
0
    js_pushboolean(J, T->type == JS_CARRAY);
832
0
  } else {
833
0
    js_pushboolean(J, 0);
834
0
  }
835
0
}
836
837
void jsB_initarray(js_State *J)
838
0
{
839
0
  js_pushobject(J, J->Array_prototype);
840
0
  {
841
0
    jsB_propf(J, "Array.prototype.toString", Ap_toString, 0);
842
0
    jsB_propf(J, "Array.prototype.concat", Ap_concat, 0); /* 1 */
843
0
    jsB_propf(J, "Array.prototype.join", Ap_join, 1);
844
0
    jsB_propf(J, "Array.prototype.pop", Ap_pop, 0);
845
0
    jsB_propf(J, "Array.prototype.push", Ap_push, 0); /* 1 */
846
0
    jsB_propf(J, "Array.prototype.reverse", Ap_reverse, 0);
847
0
    jsB_propf(J, "Array.prototype.shift", Ap_shift, 0);
848
0
    jsB_propf(J, "Array.prototype.slice", Ap_slice, 2);
849
0
    jsB_propf(J, "Array.prototype.sort", Ap_sort, 1);
850
0
    jsB_propf(J, "Array.prototype.splice", Ap_splice, 2);
851
0
    jsB_propf(J, "Array.prototype.unshift", Ap_unshift, 0); /* 1 */
852
853
    /* ES5 */
854
0
    jsB_propf(J, "Array.prototype.indexOf", Ap_indexOf, 1);
855
0
    jsB_propf(J, "Array.prototype.lastIndexOf", Ap_lastIndexOf, 1);
856
0
    jsB_propf(J, "Array.prototype.every", Ap_every, 1);
857
0
    jsB_propf(J, "Array.prototype.some", Ap_some, 1);
858
0
    jsB_propf(J, "Array.prototype.forEach", Ap_forEach, 1);
859
0
    jsB_propf(J, "Array.prototype.map", Ap_map, 1);
860
0
    jsB_propf(J, "Array.prototype.filter", Ap_filter, 1);
861
0
    jsB_propf(J, "Array.prototype.reduce", Ap_reduce, 1);
862
0
    jsB_propf(J, "Array.prototype.reduceRight", Ap_reduceRight, 1);
863
0
  }
864
0
  js_newcconstructor(J, jsB_new_Array, jsB_new_Array, "Array", 0); /* 1 */
865
0
  {
866
    /* ES5 */
867
0
    jsB_propf(J, "Array.isArray", A_isArray, 1);
868
0
  }
869
0
  js_defglobal(J, "Array", JS_DONTENUM);
870
0
}