@ugo-studio/jspp 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/analysis/scope.js +17 -0
  2. package/dist/analysis/typeAnalyzer.js +7 -1
  3. package/dist/ast/symbols.js +29 -0
  4. package/dist/ast/types.js +0 -6
  5. package/dist/cli-utils/args.js +57 -0
  6. package/dist/cli-utils/colors.js +9 -0
  7. package/dist/cli-utils/file-utils.js +20 -0
  8. package/dist/cli-utils/spinner.js +55 -0
  9. package/dist/cli.js +105 -30
  10. package/dist/core/codegen/class-handlers.js +10 -6
  11. package/dist/core/codegen/control-flow-handlers.js +31 -21
  12. package/dist/core/codegen/declaration-handlers.js +10 -6
  13. package/dist/core/codegen/expression-handlers.js +202 -60
  14. package/dist/core/codegen/function-handlers.js +179 -70
  15. package/dist/core/codegen/helpers.js +107 -17
  16. package/dist/core/codegen/index.js +9 -8
  17. package/dist/core/codegen/literal-handlers.js +15 -6
  18. package/dist/core/codegen/statement-handlers.js +67 -53
  19. package/dist/core/codegen/visitor.js +3 -1
  20. package/package.json +1 -1
  21. package/src/prelude/any_value.hpp +195 -342
  22. package/src/prelude/any_value_access.hpp +78 -30
  23. package/src/prelude/any_value_defines.hpp +74 -35
  24. package/src/prelude/any_value_helpers.hpp +73 -180
  25. package/src/prelude/exception.hpp +1 -0
  26. package/src/prelude/exception_helpers.hpp +4 -4
  27. package/src/prelude/index.hpp +9 -2
  28. package/src/prelude/library/array.hpp +190 -0
  29. package/src/prelude/library/console.hpp +6 -5
  30. package/src/prelude/library/error.hpp +10 -8
  31. package/src/prelude/library/function.hpp +10 -0
  32. package/src/prelude/library/global.hpp +20 -0
  33. package/src/prelude/library/math.hpp +308 -0
  34. package/src/prelude/library/object.hpp +288 -0
  35. package/src/prelude/library/performance.hpp +1 -1
  36. package/src/prelude/library/process.hpp +39 -0
  37. package/src/prelude/library/promise.hpp +53 -43
  38. package/src/prelude/library/symbol.hpp +45 -57
  39. package/src/prelude/library/timer.hpp +6 -6
  40. package/src/prelude/types.hpp +48 -0
  41. package/src/prelude/utils/access.hpp +182 -11
  42. package/src/prelude/utils/assignment_operators.hpp +99 -0
  43. package/src/prelude/utils/log_any_value/array.hpp +8 -8
  44. package/src/prelude/utils/log_any_value/function.hpp +6 -4
  45. package/src/prelude/utils/log_any_value/object.hpp +41 -24
  46. package/src/prelude/utils/log_any_value/primitives.hpp +3 -1
  47. package/src/prelude/utils/operators.hpp +750 -274
  48. package/src/prelude/utils/well_known_symbols.hpp +12 -0
  49. package/src/prelude/values/array.hpp +8 -6
  50. package/src/prelude/values/descriptors.hpp +2 -2
  51. package/src/prelude/values/function.hpp +71 -62
  52. package/src/prelude/values/helpers/array.hpp +64 -28
  53. package/src/prelude/values/helpers/function.hpp +77 -92
  54. package/src/prelude/values/helpers/iterator.hpp +3 -3
  55. package/src/prelude/values/helpers/object.hpp +54 -9
  56. package/src/prelude/values/helpers/promise.hpp +3 -3
  57. package/src/prelude/values/iterator.hpp +1 -1
  58. package/src/prelude/values/object.hpp +10 -3
  59. package/src/prelude/values/promise.hpp +3 -3
  60. package/src/prelude/values/prototypes/array.hpp +851 -12
  61. package/src/prelude/values/prototypes/function.hpp +2 -2
  62. package/src/prelude/values/prototypes/iterator.hpp +5 -5
  63. package/src/prelude/values/prototypes/number.hpp +153 -0
  64. package/src/prelude/values/prototypes/object.hpp +2 -2
  65. package/src/prelude/values/prototypes/promise.hpp +40 -30
  66. package/src/prelude/values/prototypes/string.hpp +28 -28
  67. package/src/prelude/values/prototypes/symbol.hpp +20 -3
  68. package/src/prelude/values/shape.hpp +52 -0
@@ -15,9 +15,9 @@ namespace jspp
15
15
  inline std::optional<AnyValue> get(const std::string &key, JsArray *self)
16
16
  {
17
17
  // --- toString() method ---
18
- if (key == "toString" )
18
+ if (key == "toString" || key == WellKnownSymbols::toStringTag->key)
19
19
  {
20
- return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &_) -> AnyValue
20
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> _) -> AnyValue
21
21
  { return AnyValue::make_string(self->to_std_string()); },
22
22
  key);
23
23
  }
@@ -25,7 +25,7 @@ namespace jspp
25
25
  // --- [Symbol.iterator]() method ---
26
26
  if (key == WellKnownSymbols::iterator->key)
27
27
  {
28
- return AnyValue::make_generator([self](const AnyValue &thisVal, const std::vector<AnyValue> &_) -> AnyValue
28
+ return AnyValue::make_generator([self](const AnyValue &thisVal, std::span<const AnyValue> _) -> AnyValue
29
29
  { return AnyValue::from_iterator(self->get_iterator()); },
30
30
  key);
31
31
  }
@@ -33,12 +33,12 @@ namespace jspp
33
33
  // --- length property ---
34
34
  if (key == "length")
35
35
  {
36
- auto getter = [self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
36
+ auto getter = [self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
37
37
  {
38
38
  return AnyValue::make_number(self->length);
39
39
  };
40
40
 
41
- auto setter = [self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
41
+ auto setter = [self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
42
42
  {
43
43
  if (args.empty())
44
44
  {
@@ -86,7 +86,7 @@ namespace jspp
86
86
  // --- push() method ---
87
87
  if (key == "push")
88
88
  {
89
- return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
89
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
90
90
  {
91
91
  for (const auto &arg : args)
92
92
  {
@@ -99,7 +99,7 @@ namespace jspp
99
99
  // --- pop() method ---
100
100
  if (key == "pop")
101
101
  {
102
- return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
102
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
103
103
  {
104
104
  if (self->length == 0)
105
105
  {
@@ -124,7 +124,7 @@ namespace jspp
124
124
  // --- shift() method ---
125
125
  if (key == "shift")
126
126
  {
127
- return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
127
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
128
128
  {
129
129
  if (self->length == 0)
130
130
  {
@@ -155,7 +155,7 @@ namespace jspp
155
155
  // --- unshift() method ---
156
156
  if (key == "unshift")
157
157
  {
158
- return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
158
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
159
159
  {
160
160
  size_t args_count = args.size();
161
161
  if (args_count == 0)
@@ -182,7 +182,7 @@ namespace jspp
182
182
  // --- join() method ---
183
183
  if (key == "join")
184
184
  {
185
- return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
185
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
186
186
  {
187
187
  std::string sep = ",";
188
188
  if (!args.empty() && !args[0].is_undefined())
@@ -210,7 +210,7 @@ namespace jspp
210
210
  // --- forEach() method ---
211
211
  if (key == "forEach")
212
212
  {
213
- return AnyValue::make_function([self](const AnyValue &thisVal, const std::vector<AnyValue> &args) -> AnyValue
213
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
214
214
  {
215
215
  if (args.empty() || !args[0].is_function())
216
216
  {
@@ -222,13 +222,852 @@ namespace jspp
222
222
  AnyValue val = self->get_property(static_cast<uint32_t>(i));
223
223
  if (!val.is_undefined())
224
224
  { // forEach skips empty slots
225
- callback->call(thisVal, {val, AnyValue::make_number(i)});
225
+ AnyValue iVal = AnyValue::make_number(i);
226
+ const AnyValue cbArgs[] = {val, iVal, thisVal};
227
+ callback->call(thisVal, cbArgs);
226
228
  }
227
229
  }
228
230
  return AnyValue::make_undefined(); },
229
231
  key);
230
232
  }
231
233
 
234
+ // --- at(index) ---
235
+ if (key == "at")
236
+ {
237
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
238
+ {
239
+ double len = static_cast<double>(self->length);
240
+ double relativeIndex = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
241
+ double k;
242
+ if (relativeIndex >= 0) k = relativeIndex;
243
+ else k = len + relativeIndex;
244
+ if (k < 0 || k >= len) return AnyValue::make_undefined();
245
+ return self->get_property(static_cast<uint32_t>(k)); },
246
+ key);
247
+ }
248
+
249
+ // --- includes(searchElement, fromIndex) ---
250
+ if (key == "includes")
251
+ {
252
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
253
+ {
254
+ AnyValue searchElement = args.empty() ? AnyValue::make_undefined() : args[0];
255
+ double len = static_cast<double>(self->length);
256
+ if (len == 0) return AnyValue::make_boolean(false);
257
+ double n = (args.size() > 1) ? Operators_Private::ToNumber(args[1]) : 0;
258
+ double k;
259
+ if (n >= 0) k = n;
260
+ else k = len + n;
261
+ if (k < 0) k = 0;
262
+
263
+ for (uint64_t i = static_cast<uint64_t>(k); i < self->length; ++i)
264
+ {
265
+ AnyValue element = self->get_property(static_cast<uint32_t>(i));
266
+ // SameValueZero algorithm (includes handles NaN)
267
+ if (element.is_number() && searchElement.is_number() && std::isnan(element.as_double()) && std::isnan(searchElement.as_double())) return AnyValue::make_boolean(true);
268
+ if (is_strictly_equal_to_primitive(element, searchElement)) return AnyValue::make_boolean(true);
269
+ }
270
+ return AnyValue::make_boolean(false); },
271
+ key);
272
+ }
273
+
274
+ // --- indexOf(searchElement, fromIndex) ---
275
+ if (key == "indexOf")
276
+ {
277
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
278
+ {
279
+ AnyValue searchElement = args.empty() ? AnyValue::make_undefined() : args[0];
280
+ double len = static_cast<double>(self->length);
281
+ if (len == 0) return AnyValue::make_number(-1);
282
+ double n = (args.size() > 1) ? Operators_Private::ToNumber(args[1]) : 0;
283
+ double k;
284
+ if (n >= 0) k = n;
285
+ else k = len + n;
286
+ if (k < 0) k = 0;
287
+
288
+ for (uint64_t i = static_cast<uint64_t>(k); i < self->length; ++i)
289
+ {
290
+ if (self->has_property(std::to_string(i))) {
291
+ AnyValue element = self->get_property(static_cast<uint32_t>(i));
292
+ if (is_strictly_equal_to_primitive(element, searchElement)) return AnyValue::make_number(i);
293
+ }
294
+ }
295
+ return AnyValue::make_number(-1); },
296
+ key);
297
+ }
298
+
299
+ // --- lastIndexOf(searchElement, fromIndex) ---
300
+ if (key == "lastIndexOf")
301
+ {
302
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
303
+ {
304
+ AnyValue searchElement = args.empty() ? AnyValue::make_undefined() : args[0];
305
+ double len = static_cast<double>(self->length);
306
+ if (len == 0) return AnyValue::make_number(-1);
307
+ double n = (args.size() > 1) ? Operators_Private::ToNumber(args[1]) : len - 1;
308
+ double k;
309
+ if (n >= 0) k = std::min(n, len - 1);
310
+ else k = len + n;
311
+
312
+ if (k < 0) return AnyValue::make_number(-1);
313
+
314
+ for (int64_t i = static_cast<int64_t>(k); i >= 0; --i)
315
+ {
316
+ if (self->has_property(std::to_string(i))) {
317
+ AnyValue element = self->get_property(static_cast<uint32_t>(i));
318
+ if (is_strictly_equal_to_primitive(element, searchElement)) return AnyValue::make_number(i);
319
+ }
320
+ }
321
+ return AnyValue::make_number(-1); },
322
+ key);
323
+ }
324
+
325
+ // --- find(callback, thisArg) ---
326
+ if (key == "find")
327
+ {
328
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
329
+ {
330
+ if (args.empty() || !args[0].is_function()) throw Exception::make_exception("callback is not a function", "TypeError");
331
+ auto callback = args[0].as_function();
332
+ auto thisArg = (args.size() > 1) ? args[1] : Constants::UNDEFINED;
333
+
334
+ for (uint64_t i = 0; i < self->length; ++i)
335
+ {
336
+ AnyValue element = self->get_property(static_cast<uint32_t>(i));
337
+ AnyValue kVal = AnyValue::make_number(i);
338
+ const AnyValue cbArgs[] = {element, kVal, thisVal};
339
+
340
+ if (is_truthy(callback->call(thisArg, std::span<const AnyValue>(cbArgs, 3)))) {
341
+ return element;
342
+ }
343
+ }
344
+ return AnyValue::make_undefined(); },
345
+ key);
346
+ }
347
+
348
+ // --- findIndex(callback, thisArg) ---
349
+ if (key == "findIndex")
350
+ {
351
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
352
+ {
353
+ if (args.empty() || !args[0].is_function()) throw Exception::make_exception("callback is not a function", "TypeError");
354
+ auto callback = args[0].as_function();
355
+ auto thisArg = (args.size() > 1) ? args[1] : Constants::UNDEFINED;
356
+
357
+ for (uint64_t i = 0; i < self->length; ++i)
358
+ {
359
+ AnyValue element = self->get_property(static_cast<uint32_t>(i));
360
+ AnyValue kVal = AnyValue::make_number(i);
361
+ const AnyValue cbArgs[] = {element, kVal, thisVal};
362
+
363
+ if (is_truthy(callback->call(thisArg, std::span<const AnyValue>(cbArgs, 3)))) {
364
+ return AnyValue::make_number(i);
365
+ }
366
+ }
367
+ return AnyValue::make_number(-1); },
368
+ key);
369
+ }
370
+
371
+ // --- findLast(callback, thisArg) ---
372
+ if (key == "findLast")
373
+ {
374
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
375
+ {
376
+ if (args.empty() || !args[0].is_function()) throw Exception::make_exception("callback is not a function", "TypeError");
377
+ auto callback = args[0].as_function();
378
+ auto thisArg = (args.size() > 1) ? args[1] : Constants::UNDEFINED;
379
+
380
+ for (int64_t i = self->length - 1; i >= 0; --i)
381
+ {
382
+ AnyValue element = self->get_property(static_cast<uint32_t>(i));
383
+ AnyValue kVal = AnyValue::make_number(i);
384
+ const AnyValue cbArgs[] = {element, kVal, thisVal};
385
+
386
+ if (is_truthy(callback->call(thisArg, std::span<const AnyValue>(cbArgs, 3)))) {
387
+ return element;
388
+ }
389
+ }
390
+ return AnyValue::make_undefined(); },
391
+ key);
392
+ }
393
+
394
+ // --- findLastIndex(callback, thisArg) ---
395
+ if (key == "findLastIndex")
396
+ {
397
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
398
+ {
399
+ if (args.empty() || !args[0].is_function()) throw Exception::make_exception("callback is not a function", "TypeError");
400
+ auto callback = args[0].as_function();
401
+ auto thisArg = (args.size() > 1) ? args[1] : Constants::UNDEFINED;
402
+
403
+ for (int64_t i = self->length - 1; i >= 0; --i)
404
+ {
405
+ AnyValue element = self->get_property(static_cast<uint32_t>(i));
406
+ AnyValue kVal = AnyValue::make_number(i);
407
+ const AnyValue cbArgs[] = {element, kVal, thisVal};
408
+
409
+ if (is_truthy(callback->call(thisArg, std::span<const AnyValue>(cbArgs, 3)))) {
410
+ return AnyValue::make_number(i);
411
+ }
412
+ }
413
+ return AnyValue::make_number(-1); },
414
+ key);
415
+ }
416
+
417
+ // --- values() ---
418
+ if (key == "values")
419
+ {
420
+ return AnyValue::make_generator([self](const AnyValue &thisVal, std::span<const AnyValue> _) -> jspp::JsIterator<jspp::AnyValue>
421
+ { return self->get_iterator(); },
422
+ key);
423
+ }
424
+
425
+ // --- keys() ---
426
+ if (key == "keys")
427
+ {
428
+ return AnyValue::make_generator([self](const AnyValue &thisVal, std::span<const AnyValue> _) -> jspp::JsIterator<jspp::AnyValue>
429
+ {
430
+ // Generator for keys
431
+ for (uint64_t i = 0; i < self->length; ++i) {
432
+ co_yield AnyValue::make_number(i);
433
+ }
434
+ co_return AnyValue::make_undefined(); },
435
+ key);
436
+ }
437
+
438
+ // --- entries() ---
439
+ if (key == "entries")
440
+ {
441
+ return AnyValue::make_generator([self](const AnyValue &thisVal, std::span<const AnyValue> _) -> jspp::JsIterator<jspp::AnyValue>
442
+ {
443
+ // Generator for [key, value]
444
+ for (uint64_t i = 0; i < self->length; ++i) {
445
+ std::vector<AnyValue> entry;
446
+ entry.push_back(AnyValue::make_number(i));
447
+ entry.push_back(self->get_property(static_cast<uint32_t>(i)));
448
+ co_yield AnyValue::make_array(std::move(entry));
449
+ }
450
+ co_return AnyValue::make_undefined(); },
451
+ key);
452
+ }
453
+
454
+ // --- map(callback, thisArg) ---
455
+ if (key == "map")
456
+ {
457
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
458
+ {
459
+ if (args.empty() || !args[0].is_function()) throw Exception::make_exception("callback is not a function", "TypeError");
460
+ auto callback = args[0].as_function();
461
+ auto thisArg = (args.size() > 1) ? args[1] : Constants::UNDEFINED;
462
+
463
+ std::vector<AnyValue> result;
464
+ result.reserve(self->length);
465
+
466
+ for (uint64_t i = 0; i < self->length; ++i) {
467
+ if (self->has_property(std::to_string(i))) {
468
+ AnyValue val = self->get_property(static_cast<uint32_t>(i));
469
+ AnyValue kVal = AnyValue::make_number(i);
470
+ const AnyValue cbArgs[] = {val, kVal, thisVal};
471
+ result.push_back(callback->call(thisArg, std::span<const AnyValue>(cbArgs, 3)));
472
+ } else {
473
+ result.push_back(Constants::UNINITIALIZED);
474
+ }
475
+ }
476
+ return AnyValue::make_array(std::move(result)); },
477
+ key);
478
+ }
479
+
480
+ // --- filter(callback, thisArg) ---
481
+ if (key == "filter")
482
+ {
483
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
484
+ {
485
+ if (args.empty() || !args[0].is_function()) throw Exception::make_exception("callback is not a function", "TypeError");
486
+ auto callback = args[0].as_function();
487
+ auto thisArg = (args.size() > 1) ? args[1] : Constants::UNDEFINED;
488
+
489
+ std::vector<AnyValue> result;
490
+
491
+ for (uint64_t i = 0; i < self->length; ++i) {
492
+ if (self->has_property(std::to_string(i))) {
493
+ AnyValue val = self->get_property(static_cast<uint32_t>(i));
494
+ AnyValue kVal = AnyValue::make_number(i);
495
+ const AnyValue cbArgs[] = {val, kVal, thisVal};
496
+ if (is_truthy(callback->call(thisArg, std::span<const AnyValue>(cbArgs, 3)))) {
497
+ result.push_back(val);
498
+ }
499
+ }
500
+ }
501
+ return AnyValue::make_array(std::move(result)); },
502
+ key);
503
+ }
504
+
505
+ // --- every(callback, thisArg) ---
506
+ if (key == "every")
507
+ {
508
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
509
+ {
510
+ if (args.empty() || !args[0].is_function()) throw Exception::make_exception("callback is not a function", "TypeError");
511
+ auto callback = args[0].as_function();
512
+ auto thisArg = (args.size() > 1) ? args[1] : Constants::UNDEFINED;
513
+
514
+ for (uint64_t i = 0; i < self->length; ++i) {
515
+ if (self->has_property(std::to_string(i))) {
516
+ AnyValue val = self->get_property(static_cast<uint32_t>(i));
517
+ AnyValue kVal = AnyValue::make_number(i);
518
+ const AnyValue cbArgs[] = {val, kVal, thisVal};
519
+ if (!is_truthy(callback->call(thisArg, std::span<const AnyValue>(cbArgs, 3)))) {
520
+ return AnyValue::make_boolean(false);
521
+ }
522
+ }
523
+ }
524
+ return AnyValue::make_boolean(true); },
525
+ key);
526
+ }
527
+
528
+ // --- some(callback, thisArg) ---
529
+ if (key == "some")
530
+ {
531
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
532
+ {
533
+ if (args.empty() || !args[0].is_function()) throw Exception::make_exception("callback is not a function", "TypeError");
534
+ auto callback = args[0].as_function();
535
+ auto thisArg = (args.size() > 1) ? args[1] : Constants::UNDEFINED;
536
+
537
+ for (uint64_t i = 0; i < self->length; ++i) {
538
+ if (self->has_property(std::to_string(i))) {
539
+ AnyValue val = self->get_property(static_cast<uint32_t>(i));
540
+ AnyValue kVal = AnyValue::make_number(i);
541
+ const AnyValue cbArgs[] = {val, kVal, thisVal};
542
+ if (is_truthy(callback->call(thisArg, std::span<const AnyValue>(cbArgs, 3)))) {
543
+ return AnyValue::make_boolean(true);
544
+ }
545
+ }
546
+ }
547
+ return AnyValue::make_boolean(false); },
548
+ key);
549
+ }
550
+
551
+ // --- reduce(callback, initialValue) ---
552
+ if (key == "reduce")
553
+ {
554
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
555
+ {
556
+ if (args.empty() || !args[0].is_function()) throw Exception::make_exception("callback is not a function", "TypeError");
557
+ auto callback = args[0].as_function();
558
+
559
+ uint64_t i = 0;
560
+ AnyValue accumulator;
561
+
562
+ if (args.size() > 1) {
563
+ accumulator = args[1];
564
+ } else {
565
+ if (self->length == 0) throw Exception::make_exception("Reduce of empty array with no initial value", "TypeError");
566
+ bool found = false;
567
+ for (; i < self->length; ++i) {
568
+ if (self->has_property(std::to_string(i))) {
569
+ accumulator = self->get_property(static_cast<uint32_t>(i));
570
+ found = true;
571
+ i++;
572
+ break;
573
+ }
574
+ }
575
+ if (!found) throw Exception::make_exception("Reduce of empty array with no initial value", "TypeError");
576
+ }
577
+
578
+ for (; i < self->length; ++i) {
579
+ if (self->has_property(std::to_string(i))) {
580
+ AnyValue val = self->get_property(static_cast<uint32_t>(i));
581
+ AnyValue kVal = AnyValue::make_number(i);
582
+ const AnyValue cbArgs[] = {accumulator, val, kVal, thisVal};
583
+ accumulator = callback->call(Constants::UNDEFINED, std::span<const AnyValue>(cbArgs, 4));
584
+ }
585
+ }
586
+ return accumulator; },
587
+ key);
588
+ }
589
+
590
+ // --- reduceRight(callback, initialValue) ---
591
+ if (key == "reduceRight")
592
+ {
593
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
594
+ {
595
+ if (args.empty() || !args[0].is_function()) throw Exception::make_exception("callback is not a function", "TypeError");
596
+ auto callback = args[0].as_function();
597
+
598
+ int64_t i = self->length - 1;
599
+ AnyValue accumulator;
600
+
601
+ if (args.size() > 1) {
602
+ accumulator = args[1];
603
+ } else {
604
+ if (self->length == 0) throw Exception::make_exception("Reduce of empty array with no initial value", "TypeError");
605
+ bool found = false;
606
+ for (; i >= 0; --i) {
607
+ if (self->has_property(std::to_string(i))) {
608
+ accumulator = self->get_property(static_cast<uint32_t>(i));
609
+ found = true;
610
+ i--;
611
+ break;
612
+ }
613
+ }
614
+ if (!found) throw Exception::make_exception("Reduce of empty array with no initial value", "TypeError");
615
+ }
616
+
617
+ for (; i >= 0; --i) {
618
+ if (self->has_property(std::to_string(i))) {
619
+ AnyValue val = self->get_property(static_cast<uint32_t>(i));
620
+ AnyValue kVal = AnyValue::make_number(i);
621
+ const AnyValue cbArgs[] = {accumulator, val, kVal, thisVal};
622
+ accumulator = callback->call(Constants::UNDEFINED, std::span<const AnyValue>(cbArgs, 4));
623
+ }
624
+ }
625
+ return accumulator; },
626
+ key);
627
+ }
628
+
629
+ // --- flat(depth) ---
630
+ if (key == "flat")
631
+ {
632
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
633
+ {
634
+ double depthVal = (args.size() > 0 && !args[0].is_undefined()) ? Operators_Private::ToNumber(args[0]) : 1;
635
+ int depth = static_cast<int>(depthVal);
636
+ if (depth < 0) depth = 0;
637
+
638
+ std::vector<AnyValue> result;
639
+ std::function<void(const AnyValue&, int)> flatten;
640
+ flatten = [&result, &flatten](const AnyValue& item, int d) {
641
+ if (d > 0 && item.is_array()) {
642
+ auto arr = item.as_array();
643
+ for (uint64_t i = 0; i < arr->length; ++i) {
644
+ if (arr->has_property(std::to_string(i))) {
645
+ flatten(arr->get_property(static_cast<uint32_t>(i)), d - 1);
646
+ }
647
+ }
648
+ } else {
649
+ result.push_back(item);
650
+ }
651
+ };
652
+
653
+ for (uint64_t i = 0; i < self->length; ++i) {
654
+ if (self->has_property(std::to_string(i))) {
655
+ flatten(self->get_property(static_cast<uint32_t>(i)), depth);
656
+ }
657
+ }
658
+ return AnyValue::make_array(std::move(result)); },
659
+ key);
660
+ }
661
+
662
+ // --- flatMap(callback, thisArg) ---
663
+ if (key == "flatMap")
664
+ {
665
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
666
+ {
667
+ if (args.empty() || !args[0].is_function()) throw Exception::make_exception("callback is not a function", "TypeError");
668
+ auto callback = args[0].as_function();
669
+ auto thisArg = (args.size() > 1) ? args[1] : Constants::UNDEFINED;
670
+
671
+ std::vector<AnyValue> result;
672
+
673
+ for (uint64_t i = 0; i < self->length; ++i) {
674
+ if (self->has_property(std::to_string(i))) {
675
+ AnyValue val = self->get_property(static_cast<uint32_t>(i));
676
+ AnyValue kVal = AnyValue::make_number(i);
677
+ const AnyValue cbArgs[] = {val, kVal, thisVal};
678
+ AnyValue mapped = callback->call(thisArg, std::span<const AnyValue>(cbArgs, 3));
679
+
680
+ if (mapped.is_array()) {
681
+ auto arr = mapped.as_array();
682
+ for (uint64_t j = 0; j < arr->length; ++j) {
683
+ if (arr->has_property(std::to_string(j))) {
684
+ result.push_back(arr->get_property(static_cast<uint32_t>(j)));
685
+ }
686
+ }
687
+ } else {
688
+ result.push_back(mapped);
689
+ }
690
+ }
691
+ }
692
+ return AnyValue::make_array(std::move(result)); },
693
+ key);
694
+ }
695
+
696
+ // --- fill(value, start, end) ---
697
+ if (key == "fill")
698
+ {
699
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
700
+ {
701
+ AnyValue value = args.empty() ? AnyValue::make_undefined() : args[0];
702
+ double len = static_cast<double>(self->length);
703
+ double start = (args.size() > 1) ? Operators_Private::ToNumber(args[1]) : 0;
704
+ double end = (args.size() > 2 && !args[2].is_undefined()) ? Operators_Private::ToNumber(args[2]) : len;
705
+
706
+ double k;
707
+ if (start >= 0) k = start; else k = len + start;
708
+ if (k < 0) k = 0;
709
+
710
+ double final;
711
+ if (end >= 0) final = end; else final = len + end;
712
+ if (final > len) final = len;
713
+
714
+ for (uint64_t i = static_cast<uint64_t>(k); i < static_cast<uint64_t>(final); ++i) {
715
+ self->set_property(static_cast<uint32_t>(i), value);
716
+ }
717
+ return thisVal; },
718
+ key);
719
+ }
720
+
721
+ // --- reverse() ---
722
+ if (key == "reverse")
723
+ {
724
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
725
+ {
726
+ uint64_t len = self->length;
727
+ for (uint64_t i = 0; i < len / 2; ++i) {
728
+ uint64_t j = len - 1 - i;
729
+ bool hasI = self->has_property(std::to_string(i));
730
+ bool hasJ = self->has_property(std::to_string(j));
731
+
732
+ if (hasI && hasJ) {
733
+ AnyValue valI = self->get_property(static_cast<uint32_t>(i));
734
+ AnyValue valJ = self->get_property(static_cast<uint32_t>(j));
735
+ self->set_property(static_cast<uint32_t>(i), valJ);
736
+ self->set_property(static_cast<uint32_t>(j), valI);
737
+ } else if (hasI && !hasJ) {
738
+ AnyValue valI = self->get_property(static_cast<uint32_t>(i));
739
+ self->set_property(static_cast<uint32_t>(j), valI);
740
+ if (i < self->dense.size()) self->dense[i] = Constants::UNINITIALIZED;
741
+ else self->sparse.erase(static_cast<uint32_t>(i));
742
+ } else if (!hasI && hasJ) {
743
+ AnyValue valJ = self->get_property(static_cast<uint32_t>(j));
744
+ self->set_property(static_cast<uint32_t>(i), valJ);
745
+ if (j < self->dense.size()) self->dense[j] = Constants::UNINITIALIZED;
746
+ else self->sparse.erase(static_cast<uint32_t>(j));
747
+ }
748
+ }
749
+ return thisVal; },
750
+ key);
751
+ }
752
+
753
+ // --- sort(compareFn) ---
754
+ if (key == "sort")
755
+ {
756
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
757
+ {
758
+ AnyValue compareFn = args.empty() ? AnyValue::make_undefined() : args[0];
759
+
760
+ std::vector<AnyValue> items;
761
+ for (uint64_t i = 0; i < self->length; ++i) {
762
+ if (self->has_property(std::to_string(i))) {
763
+ items.push_back(self->get_property(static_cast<uint32_t>(i)));
764
+ }
765
+ }
766
+
767
+ std::sort(items.begin(), items.end(), [&](const AnyValue& a, const AnyValue& b) {
768
+ if (a.is_undefined() && b.is_undefined()) return false;
769
+ if (a.is_undefined()) return false;
770
+ if (b.is_undefined()) return true;
771
+
772
+ if (compareFn.is_function()) {
773
+ const AnyValue cmpArgs[] = {a, b};
774
+ double res = Operators_Private::ToNumber(compareFn.call(Constants::UNDEFINED, std::span<const AnyValue>(cmpArgs, 2)));
775
+ return res < 0;
776
+ } else {
777
+ std::string sA = a.to_std_string();
778
+ std::string sB = b.to_std_string();
779
+ return sA < sB;
780
+ }
781
+ });
782
+
783
+ for (uint64_t i = 0; i < items.size(); ++i) {
784
+ self->set_property(static_cast<uint32_t>(i), items[i]);
785
+ }
786
+ for (uint64_t i = items.size(); i < self->length; ++i) {
787
+ if (i < self->dense.size()) self->dense[i] = Constants::UNINITIALIZED;
788
+ else self->sparse.erase(static_cast<uint32_t>(i));
789
+ }
790
+
791
+ return thisVal; },
792
+ key);
793
+ }
794
+
795
+ // --- splice(start, deleteCount, ...items) ---
796
+ if (key == "splice")
797
+ {
798
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
799
+ {
800
+ double len = static_cast<double>(self->length);
801
+ double start = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
802
+ double actualStart = (start < 0) ? std::max(len + start, 0.0) : std::min(start, len);
803
+
804
+ uint64_t startIdx = static_cast<uint64_t>(actualStart);
805
+ uint64_t deleteCount = 0;
806
+ if (args.size() >= 2) {
807
+ double dc = Operators_Private::ToNumber(args[1]);
808
+ deleteCount = static_cast<uint64_t>(std::max(0.0, std::min(dc, len - startIdx)));
809
+ } else if (args.size() == 1) {
810
+ deleteCount = len - startIdx;
811
+ }
812
+
813
+ std::vector<AnyValue> deletedItems;
814
+ for (uint64_t i = 0; i < deleteCount; ++i) {
815
+ if (self->has_property(std::to_string(startIdx + i))) {
816
+ deletedItems.push_back(self->get_property(static_cast<uint32_t>(startIdx + i)));
817
+ } else {
818
+ deletedItems.push_back(Constants::UNINITIALIZED);
819
+ }
820
+ }
821
+
822
+ std::vector<AnyValue> insertItems;
823
+ for (size_t i = 2; i < args.size(); ++i) {
824
+ insertItems.push_back(args[i]);
825
+ }
826
+ uint64_t insertCount = insertItems.size();
827
+
828
+ if (insertCount < deleteCount) {
829
+ for (uint64_t i = startIdx; i < len - deleteCount; ++i) {
830
+ uint64_t from = i + deleteCount;
831
+ uint64_t to = i + insertCount;
832
+ if (self->has_property(std::to_string(from))) {
833
+ self->set_property(static_cast<uint32_t>(to), self->get_property(static_cast<uint32_t>(from)));
834
+ } else {
835
+ if (to < self->dense.size()) self->dense[to] = Constants::UNINITIALIZED;
836
+ else self->sparse.erase(static_cast<uint32_t>(to));
837
+ }
838
+ }
839
+ for (uint64_t i = len; i > len - deleteCount + insertCount; --i) {
840
+ uint64_t idx = i - 1;
841
+ if (idx < self->dense.size()) self->dense[idx] = Constants::UNINITIALIZED;
842
+ else self->sparse.erase(static_cast<uint32_t>(idx));
843
+ }
844
+ } else if (insertCount > deleteCount) {
845
+ for (uint64_t i = len; i > startIdx + deleteCount; --i) {
846
+ uint64_t from = i - 1;
847
+ uint64_t to = from - deleteCount + insertCount;
848
+ if (self->has_property(std::to_string(from))) {
849
+ self->set_property(static_cast<uint32_t>(to), self->get_property(static_cast<uint32_t>(from)));
850
+ } else {
851
+ if (to < self->dense.size()) self->dense[to] = Constants::UNINITIALIZED;
852
+ else self->sparse.erase(static_cast<uint32_t>(to));
853
+ }
854
+ }
855
+ }
856
+
857
+ for (uint64_t i = 0; i < insertCount; ++i) {
858
+ self->set_property(static_cast<uint32_t>(startIdx + i), insertItems[i]);
859
+ }
860
+
861
+ self->length = len - deleteCount + insertCount;
862
+ return AnyValue::make_array(std::move(deletedItems)); },
863
+ key);
864
+ }
865
+
866
+ // --- copyWithin(target, start, end) ---
867
+ if (key == "copyWithin")
868
+ {
869
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
870
+ {
871
+ double len = static_cast<double>(self->length);
872
+ double target = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
873
+ double start = (args.size() > 1) ? Operators_Private::ToNumber(args[1]) : 0;
874
+ double end = (args.size() > 2 && !args[2].is_undefined()) ? Operators_Private::ToNumber(args[2]) : len;
875
+
876
+ double to;
877
+ if (target >= 0) to = target; else to = len + target;
878
+ if (to < 0) to = 0; else if (to > len) to = len;
879
+
880
+ double from;
881
+ if (start >= 0) from = start; else from = len + start;
882
+ if (from < 0) from = 0; else if (from > len) from = len;
883
+
884
+ double final;
885
+ if (end >= 0) final = end; else final = len + end;
886
+ if (final < 0) final = 0; else if (final > len) final = len;
887
+
888
+ double count = std::min(final - from, len - to);
889
+
890
+ if (from < to && to < from + count) {
891
+ for (double i = count - 1; i >= 0; --i) {
892
+ uint64_t f = static_cast<uint64_t>(from + i);
893
+ uint64_t t = static_cast<uint64_t>(to + i);
894
+ if (self->has_property(std::to_string(f))) {
895
+ self->set_property(static_cast<uint32_t>(t), self->get_property(static_cast<uint32_t>(f)));
896
+ } else {
897
+ if (t < self->dense.size()) self->dense[t] = Constants::UNINITIALIZED;
898
+ else self->sparse.erase(static_cast<uint32_t>(t));
899
+ }
900
+ }
901
+ } else {
902
+ for (double i = 0; i < count; ++i) {
903
+ uint64_t f = static_cast<uint64_t>(from + i);
904
+ uint64_t t = static_cast<uint64_t>(to + i);
905
+ if (self->has_property(std::to_string(f))) {
906
+ self->set_property(static_cast<uint32_t>(t), self->get_property(static_cast<uint32_t>(f)));
907
+ } else {
908
+ if (t < self->dense.size()) self->dense[t] = Constants::UNINITIALIZED;
909
+ else self->sparse.erase(static_cast<uint32_t>(t));
910
+ }
911
+ }
912
+ }
913
+ return thisVal; },
914
+ key);
915
+ }
916
+
917
+ // --- concat(...items) ---
918
+ if (key == "concat")
919
+ {
920
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
921
+ {
922
+ std::vector<AnyValue> result;
923
+ for (uint64_t i = 0; i < self->length; ++i) {
924
+ if (self->has_property(std::to_string(i))) {
925
+ result.push_back(self->get_property(static_cast<uint32_t>(i)));
926
+ } else {
927
+ result.push_back(Constants::UNINITIALIZED);
928
+ }
929
+ }
930
+
931
+ for (const auto& item : args) {
932
+ bool spreadable = false;
933
+ if (item.is_array()) {
934
+ spreadable = true;
935
+ auto sym = WellKnownSymbols::isConcatSpreadable;
936
+ if (item.has_property(sym->key)) {
937
+ spreadable = is_truthy(item.get_property_with_receiver(sym->key, item));
938
+ }
939
+ } else if (item.is_object()) {
940
+ auto sym = WellKnownSymbols::isConcatSpreadable;
941
+ if (item.has_property(sym->key)) {
942
+ spreadable = is_truthy(item.get_property_with_receiver(sym->key, item));
943
+ }
944
+ }
945
+
946
+ if (spreadable && item.is_array()) {
947
+ auto arr = item.as_array();
948
+ for (uint64_t i = 0; i < arr->length; ++i) {
949
+ if (arr->has_property(std::to_string(i))) {
950
+ result.push_back(arr->get_property(static_cast<uint32_t>(i)));
951
+ } else {
952
+ result.push_back(Constants::UNINITIALIZED);
953
+ }
954
+ }
955
+ } else {
956
+ result.push_back(item);
957
+ }
958
+ }
959
+ return AnyValue::make_array(std::move(result)); },
960
+ key);
961
+ }
962
+
963
+ // --- slice(start, end) ---
964
+ if (key == "slice")
965
+ {
966
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
967
+ {
968
+ double len = static_cast<double>(self->length);
969
+ double start = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
970
+ double end = (args.size() < 2 || args[1].is_undefined()) ? len : Operators_Private::ToNumber(args[1]);
971
+
972
+ double k;
973
+ if (start >= 0) k = start; else k = len + start;
974
+ if (k < 0) k = 0;
975
+
976
+ double final;
977
+ if (end >= 0) final = end; else final = len + end;
978
+ if (final > len) final = len;
979
+
980
+ if (final < k) final = k;
981
+
982
+ std::vector<AnyValue> result;
983
+ for (uint64_t i = static_cast<uint64_t>(k); i < static_cast<uint64_t>(final); ++i) {
984
+ if (self->has_property(std::to_string(i))) {
985
+ result.push_back(self->get_property(static_cast<uint32_t>(i)));
986
+ } else {
987
+ result.push_back(Constants::UNINITIALIZED);
988
+ }
989
+ }
990
+ return AnyValue::make_array(std::move(result)); },
991
+ key);
992
+ }
993
+
994
+ // --- toReversed() ---
995
+ if (key == "toReversed")
996
+ {
997
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
998
+ {
999
+ auto copy = self->get_property("slice", thisVal).call(thisVal, {});
1000
+ copy.get_own_property("reverse").call(copy, {});
1001
+ return copy; },
1002
+ key);
1003
+ }
1004
+
1005
+ // --- toSorted(compareFn) ---
1006
+ if (key == "toSorted")
1007
+ {
1008
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
1009
+ {
1010
+ auto copy = self->get_property("slice", thisVal).call(thisVal, {});
1011
+ copy.get_own_property("sort").call(copy, args);
1012
+ return copy; },
1013
+ key);
1014
+ }
1015
+
1016
+ // --- toSpliced(start, deleteCount, ...items) ---
1017
+ if (key == "toSpliced")
1018
+ {
1019
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
1020
+ {
1021
+ auto copy = self->get_property("slice", thisVal).call(thisVal, {});
1022
+ copy.get_own_property("splice").call(copy, args);
1023
+ return copy; },
1024
+ key);
1025
+ }
1026
+
1027
+ // --- with(index, value) ---
1028
+ if (key == "with")
1029
+ {
1030
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
1031
+ {
1032
+ auto copy = self->get_property("slice", thisVal).call(thisVal, {});
1033
+
1034
+ double len = static_cast<double>(self->length);
1035
+ double idx = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
1036
+ double k;
1037
+ if (idx >= 0) k = idx; else k = len + idx;
1038
+
1039
+ if (k < 0 || k >= len) throw Exception::make_exception("Invalid index", "RangeError");
1040
+
1041
+ AnyValue value = (args.size() > 1) ? args[1] : Constants::UNDEFINED;
1042
+ copy.set_own_property(static_cast<uint32_t>(k), value);
1043
+ return copy; },
1044
+ key);
1045
+ }
1046
+
1047
+ // --- toLocaleString() ---
1048
+ if (key == "toLocaleString")
1049
+ {
1050
+ return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
1051
+ {
1052
+ std::string result = "";
1053
+ for (uint64_t i = 0; i < self->length; ++i) {
1054
+ if (i > 0) result += ",";
1055
+ AnyValue element = self->get_property(static_cast<uint32_t>(i));
1056
+ if (!element.is_null() && !element.is_undefined()) {
1057
+ if (element.has_property("toLocaleString")) {
1058
+ auto fn = element.get_property_with_receiver("toLocaleString", element);
1059
+ if (fn.is_function()) {
1060
+ result += fn.call(element, {}).to_std_string();
1061
+ continue;
1062
+ }
1063
+ }
1064
+ result += element.to_std_string();
1065
+ }
1066
+ }
1067
+ return AnyValue::make_string(result); },
1068
+ key);
1069
+ }
1070
+
232
1071
  return std::nullopt;
233
1072
  }
234
1073
  }