@ugo-studio/jspp 0.2.5 → 0.2.7

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 (54) hide show
  1. package/README.md +51 -36
  2. package/dist/analysis/scope.js +7 -0
  3. package/dist/analysis/typeAnalyzer.js +96 -43
  4. package/dist/ast/symbols.js +34 -24
  5. package/dist/cli/args.js +59 -0
  6. package/dist/cli/colors.js +9 -0
  7. package/dist/cli/file-utils.js +20 -0
  8. package/dist/cli/index.js +160 -0
  9. package/dist/cli/spinner.js +55 -0
  10. package/dist/core/codegen/class-handlers.js +8 -8
  11. package/dist/core/codegen/control-flow-handlers.js +19 -9
  12. package/dist/core/codegen/declaration-handlers.js +30 -10
  13. package/dist/core/codegen/expression-handlers.js +649 -161
  14. package/dist/core/codegen/function-handlers.js +107 -103
  15. package/dist/core/codegen/helpers.js +61 -14
  16. package/dist/core/codegen/index.js +13 -9
  17. package/dist/core/codegen/literal-handlers.js +4 -2
  18. package/dist/core/codegen/statement-handlers.js +147 -55
  19. package/dist/core/codegen/visitor.js +22 -2
  20. package/dist/core/constants.js +16 -0
  21. package/dist/core/error.js +58 -0
  22. package/dist/index.js +6 -3
  23. package/package.json +3 -3
  24. package/src/prelude/any_value.hpp +89 -59
  25. package/src/prelude/any_value_access.hpp +1 -1
  26. package/src/prelude/any_value_helpers.hpp +85 -43
  27. package/src/prelude/index.hpp +1 -0
  28. package/src/prelude/library/array.hpp +3 -2
  29. package/src/prelude/scheduler.hpp +144 -144
  30. package/src/prelude/types.hpp +8 -8
  31. package/src/prelude/utils/access.hpp +62 -6
  32. package/src/prelude/utils/assignment_operators.hpp +14 -14
  33. package/src/prelude/utils/log_any_value/array.hpp +0 -15
  34. package/src/prelude/utils/log_any_value/object.hpp +12 -10
  35. package/src/prelude/utils/log_any_value/primitives.hpp +2 -0
  36. package/src/prelude/utils/operators.hpp +117 -474
  37. package/src/prelude/utils/operators_primitive.hpp +337 -0
  38. package/src/prelude/values/helpers/array.hpp +4 -4
  39. package/src/prelude/values/helpers/async_iterator.hpp +2 -2
  40. package/src/prelude/values/helpers/function.hpp +3 -3
  41. package/src/prelude/values/helpers/iterator.hpp +2 -2
  42. package/src/prelude/values/helpers/object.hpp +3 -3
  43. package/src/prelude/values/helpers/promise.hpp +1 -1
  44. package/src/prelude/values/helpers/string.hpp +1 -1
  45. package/src/prelude/values/helpers/symbol.hpp +1 -1
  46. package/src/prelude/values/prototypes/array.hpp +1125 -853
  47. package/src/prelude/values/prototypes/async_iterator.hpp +32 -14
  48. package/src/prelude/values/prototypes/function.hpp +30 -18
  49. package/src/prelude/values/prototypes/iterator.hpp +40 -17
  50. package/src/prelude/values/prototypes/number.hpp +119 -62
  51. package/src/prelude/values/prototypes/object.hpp +10 -4
  52. package/src/prelude/values/prototypes/promise.hpp +167 -109
  53. package/src/prelude/values/prototypes/string.hpp +407 -231
  54. package/src/prelude/values/prototypes/symbol.hpp +45 -23
@@ -14,353 +14,529 @@ namespace jspp
14
14
  {
15
15
  namespace StringPrototypes
16
16
  {
17
+ inline AnyValue &get_toString_fn()
18
+ {
19
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
20
+ { return AnyValue::make_string(thisVal.as_string()->value); },
21
+ "toString");
22
+ return fn;
23
+ }
24
+
25
+ inline AnyValue &get_iterator_fn()
26
+ {
27
+ static AnyValue fn = AnyValue::make_generator([](const AnyValue &thisVal, std::span<const AnyValue> _) -> AnyValue
28
+ { return AnyValue::from_iterator(thisVal.as_string()->get_iterator()); },
29
+ "Symbol.iterator");
30
+ return fn;
31
+ }
32
+
33
+ inline AnyValue &get_length_desc()
34
+ {
35
+ static auto getter = [](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
36
+ { return AnyValue::make_number(thisVal.as_string()->value.length()); };
37
+ static auto setter = [](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
38
+ { return Constants::UNDEFINED; };
39
+ static AnyValue desc = AnyValue::make_accessor_descriptor(getter, setter, false, false);
40
+ return desc;
41
+ }
42
+
43
+ inline AnyValue &get_charAt_fn()
44
+ {
45
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
46
+ {
47
+ auto self = thisVal.as_string();
48
+ double pos = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
49
+ int index = static_cast<int>(pos);
50
+ if (index < 0 || index >= self->value.length())
51
+ {
52
+ return AnyValue::make_string("");
53
+ }
54
+ return AnyValue::make_string(std::string(1, self->value[index])); },
55
+ "charAt");
56
+ return fn;
57
+ }
58
+
59
+ inline AnyValue &get_concat_fn()
60
+ {
61
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
62
+ {
63
+ std::string result = thisVal.as_string()->value;
64
+ for (const auto &arg : args)
65
+ {
66
+ result += arg.to_std_string();
67
+ }
68
+ return AnyValue::make_string(result); },
69
+ "concat");
70
+ return fn;
71
+ }
72
+
73
+ inline AnyValue &get_endsWith_fn()
74
+ {
75
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
76
+ {
77
+ auto self = thisVal.as_string();
78
+ if (args.empty())
79
+ return Constants::FALSE;
80
+ std::string search = args[0].to_std_string();
81
+ size_t end_pos = (args.size() > 1 && !args[1].is_undefined()) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : self->value.length();
82
+
83
+ if (end_pos > self->value.length())
84
+ end_pos = self->value.length();
85
+ if (search.length() > end_pos)
86
+ return Constants::FALSE;
87
+
88
+ return AnyValue::make_boolean(self->value.substr(end_pos - search.length(), search.length()) == search); },
89
+ "endsWith");
90
+ return fn;
91
+ }
92
+
93
+ inline AnyValue &get_includes_fn()
94
+ {
95
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
96
+ {
97
+ auto self = thisVal.as_string();
98
+ if (args.empty())
99
+ return Constants::FALSE;
100
+ std::string search = args[0].to_std_string();
101
+ size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
102
+
103
+ return AnyValue::make_boolean(self->value.find(search, pos) != std::string::npos); },
104
+ "includes");
105
+ return fn;
106
+ }
107
+
108
+ inline AnyValue &get_indexOf_fn()
109
+ {
110
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
111
+ {
112
+ auto self = thisVal.as_string();
113
+ if (args.empty())
114
+ return AnyValue::make_number(-1);
115
+ std::string search = args[0].to_std_string();
116
+ size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
117
+ size_t result = self->value.find(search, pos);
118
+ return result == std::string::npos ? AnyValue::make_number(-1) : AnyValue::make_number(result); },
119
+ "indexOf");
120
+ return fn;
121
+ }
122
+
123
+ inline AnyValue &get_lastIndexOf_fn()
124
+ {
125
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
126
+ {
127
+ auto self = thisVal.as_string();
128
+ if (args.empty())
129
+ return AnyValue::make_number(-1);
130
+ std::string search = args[0].to_std_string();
131
+ size_t pos = (args.size() > 1 && !args[1].is_undefined()) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : std::string::npos;
132
+ size_t result = self->value.rfind(search, pos);
133
+ return result == std::string::npos ? AnyValue::make_number(-1) : AnyValue::make_number(result); },
134
+ "lastIndexOf");
135
+ return fn;
136
+ }
137
+
138
+ inline AnyValue &get_padEnd_fn()
139
+ {
140
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
141
+ {
142
+ auto self = thisVal.as_string();
143
+ size_t target_length = args.empty() ? 0 : static_cast<size_t>(Operators_Private::ToNumber(args[0]));
144
+ if (self->value.length() >= target_length)
145
+ return AnyValue::make_string(self->value);
146
+ std::string pad_string = (args.size() > 1 && !args[1].is_undefined() && !args[1].to_std_string().empty()) ? args[1].to_std_string() : " ";
147
+ std::string result = self->value;
148
+ while (result.length() < target_length)
149
+ {
150
+ result += pad_string;
151
+ }
152
+ return AnyValue::make_string(result.substr(0, target_length)); },
153
+ "padEnd");
154
+ return fn;
155
+ }
156
+
157
+ inline AnyValue &get_padStart_fn()
158
+ {
159
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
160
+ {
161
+ auto self = thisVal.as_string();
162
+ size_t target_length = args.empty() ? 0 : static_cast<size_t>(Operators_Private::ToNumber(args[0]));
163
+ if (self->value.length() >= target_length)
164
+ return AnyValue::make_string(self->value);
165
+ std::string pad_string = (args.size() > 1 && !args[1].is_undefined() && !args[1].to_std_string().empty()) ? args[1].to_std_string() : " ";
166
+ std::string padding;
167
+ while (padding.length() < target_length - self->value.length())
168
+ {
169
+ padding += pad_string;
170
+ }
171
+ return AnyValue::make_string(padding.substr(0, target_length - self->value.length()) + self->value); },
172
+ "padStart");
173
+ return fn;
174
+ }
175
+
176
+ inline AnyValue &get_repeat_fn()
177
+ {
178
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
179
+ {
180
+ auto self = thisVal.as_string();
181
+ double count = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
182
+ if (count < 0)
183
+ {
184
+ // In a real implementation, this should throw a RangeError.
185
+ return AnyValue::make_string("");
186
+ }
187
+ std::string result = "";
188
+ for (int i = 0; i < count; ++i)
189
+ {
190
+ result += self->value;
191
+ }
192
+ return AnyValue::make_string(result); },
193
+ "repeat");
194
+ return fn;
195
+ }
196
+
197
+ inline AnyValue &get_replace_fn()
198
+ {
199
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
200
+ {
201
+ auto self = thisVal.as_string();
202
+ if (args.size() < 2)
203
+ return AnyValue::make_string(self->value);
204
+ std::string search = args[0].to_std_string();
205
+ std::string replacement = args[1].to_std_string();
206
+ std::string result = self->value;
207
+ size_t pos = result.find(search);
208
+ if (pos != std::string::npos)
209
+ {
210
+ result.replace(pos, search.length(), replacement);
211
+ }
212
+ return AnyValue::make_string(result); },
213
+ "replace");
214
+ return fn;
215
+ }
216
+
217
+ inline AnyValue &get_replaceAll_fn()
218
+ {
219
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
220
+ {
221
+ auto self = thisVal.as_string();
222
+ if (args.size() < 2)
223
+ return AnyValue::make_string(self->value);
224
+ std::string search = args[0].to_std_string();
225
+ if (search.empty())
226
+ return AnyValue::make_string(self->value);
227
+ std::string replacement = args[1].to_std_string();
228
+ std::string result = self->value;
229
+ size_t pos = result.find(search);
230
+ while (pos != std::string::npos)
231
+ {
232
+ result.replace(pos, search.length(), replacement);
233
+ pos = result.find(search, pos + replacement.length());
234
+ }
235
+ return AnyValue::make_string(result); },
236
+ "replaceAll");
237
+ return fn;
238
+ }
239
+
240
+ inline AnyValue &get_slice_fn()
241
+ {
242
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
243
+ {
244
+ auto self = thisVal.as_string();
245
+ int len = self->value.length();
246
+ int start = args.empty() ? 0 : Operators_Private::ToInt32(args[0]);
247
+ int end = (args.size() < 2 || args[1].is_undefined()) ? len : Operators_Private::ToInt32(args[1]);
248
+
249
+ if (start < 0)
250
+ start += len;
251
+ if (end < 0)
252
+ end += len;
253
+
254
+ start = std::max(0, std::min(len, start));
255
+ end = std::max(0, std::min(len, end));
256
+
257
+ if (start >= end)
258
+ return AnyValue::make_string("");
259
+ return AnyValue::make_string(self->value.substr(start, end - start)); },
260
+ "slice");
261
+ return fn;
262
+ }
263
+
264
+ inline AnyValue &get_split_fn()
265
+ {
266
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
267
+ {
268
+ auto self = thisVal.as_string();
269
+ std::string separator = (args.empty() || args[0].is_undefined()) ? "" : args[0].to_std_string();
270
+ std::vector<jspp::AnyValue> result_vec;
271
+
272
+ if (separator.empty())
273
+ {
274
+ for (char c : (self->value))
275
+ {
276
+ result_vec.push_back(AnyValue::make_string(std::string(1, c)));
277
+ }
278
+ }
279
+ else
280
+ {
281
+ std::string temp = (self->value);
282
+ size_t pos = 0;
283
+ while ((pos = temp.find(separator)) != std::string::npos)
284
+ {
285
+ result_vec.push_back(AnyValue::make_string(temp.substr(0, pos)));
286
+ temp.erase(0, pos + separator.length());
287
+ }
288
+ result_vec.push_back(AnyValue::make_string(temp));
289
+ }
290
+ return AnyValue::make_array(std::move(result_vec)); },
291
+ "split");
292
+ return fn;
293
+ }
294
+
295
+ inline AnyValue &get_startsWith_fn()
296
+ {
297
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
298
+ {
299
+ auto self = thisVal.as_string();
300
+ if (args.empty())
301
+ return Constants::FALSE;
302
+ std::string search = args[0].to_std_string();
303
+ size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
304
+ if (pos > self->value.length())
305
+ pos = self->value.length();
306
+
307
+ return AnyValue::make_boolean(self->value.rfind(search, pos) == pos); },
308
+ "startsWith");
309
+ return fn;
310
+ }
311
+
312
+ inline AnyValue &get_substring_fn()
313
+ {
314
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
315
+ {
316
+ auto self = thisVal.as_string();
317
+ int len = self->value.length();
318
+ int start = args.empty() ? 0 : Operators_Private::ToInt32(args[0]);
319
+ int end = (args.size() < 2 || args[1].is_undefined()) ? len : Operators_Private::ToInt32(args[1]);
320
+
321
+ start = std::max(0, start);
322
+ end = std::max(0, end);
323
+
324
+ if (start > end)
325
+ std::swap(start, end);
326
+
327
+ start = std::min(len, start);
328
+ end = std::min(len, end);
329
+
330
+ return AnyValue::make_string(self->value.substr(start, end - start)); },
331
+ "substring");
332
+ return fn;
333
+ }
334
+
335
+ inline AnyValue &get_toLowerCase_fn()
336
+ {
337
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
338
+ {
339
+ std::string result = thisVal.as_string()->value;
340
+ std::transform(result.begin(), result.end(), result.begin(),
341
+ [](unsigned char c)
342
+ { return std::tolower(c); });
343
+ return AnyValue::make_string(result); },
344
+ "toLowerCase");
345
+ return fn;
346
+ }
347
+
348
+ inline AnyValue &get_toUpperCase_fn()
349
+ {
350
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
351
+ {
352
+ std::string result = thisVal.as_string()->value;
353
+ std::transform(result.begin(), result.end(), result.begin(),
354
+ [](unsigned char c)
355
+ { return std::toupper(c); });
356
+ return AnyValue::make_string(result); },
357
+ "toUpperCase");
358
+ return fn;
359
+ }
360
+
361
+ inline AnyValue &get_trim_fn()
362
+ {
363
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
364
+ {
365
+ const char *whitespace = " \t\n\r\f\v";
366
+ std::string result = thisVal.as_string()->value;
367
+ result.erase(0, result.find_first_not_of(whitespace));
368
+ result.erase(result.find_last_not_of(whitespace) + 1);
369
+ return AnyValue::make_string(result); },
370
+ "trim");
371
+ return fn;
372
+ }
373
+
374
+ inline AnyValue &get_trimEnd_fn()
375
+ {
376
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
377
+ {
378
+ const char *whitespace = " \t\n\r\f\v";
379
+ std::string result = thisVal.as_string()->value;
380
+ result.erase(result.find_last_not_of(whitespace) + 1);
381
+ return AnyValue::make_string(result); },
382
+ "trimEnd");
383
+ return fn;
384
+ }
385
+
386
+ inline AnyValue &get_trimStart_fn()
387
+ {
388
+ static AnyValue fn = AnyValue::make_function([](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
389
+ {
390
+ const char *whitespace = " \t\n\r\f\v";
391
+ std::string result = thisVal.as_string()->value;
392
+ result.erase(0, result.find_first_not_of(whitespace));
393
+ return AnyValue::make_string(result); },
394
+ "trimStart");
395
+ return fn;
396
+ }
397
+
17
398
  // This function retrieves a prototype method for a given string instance.
18
- // It captures the string instance to act as the 'this' context for the method.
19
- inline std::optional<AnyValue> get(const std::string &key, JsString *self)
399
+ inline std::optional<AnyValue> get(const std::string &key)
20
400
  {
21
401
  // --- toString() & valueOf() ---
22
- if (key == "toString" || key == "valueOf" || key == WellKnownSymbols::toStringTag->key)
402
+ if (key == "toString" || key == "valueOf" || key == WellKnownSymbols::toStringTag->key)
23
403
  {
24
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
25
- { return AnyValue::make_string(self->value); },
26
- key);
404
+ return get_toString_fn();
27
405
  }
28
406
 
29
407
  // --- [Symbol.iterator]() method ---
30
408
  if (key == WellKnownSymbols::iterator->key)
31
409
  {
32
- return AnyValue::make_generator([self](const AnyValue &thisVal, std::span<const AnyValue> _) -> AnyValue
33
- { return AnyValue::from_iterator(self->get_iterator()); },
34
- key);
410
+ return get_iterator_fn();
35
411
  }
36
412
 
37
413
  // --- length property ---
38
414
  if (key == "length")
39
415
  {
40
- return AnyValue::make_accessor_descriptor([self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
41
- { return AnyValue::make_number(self->value.length()); },
42
- [self](const AnyValue &thisVal, std::span<const AnyValue>) -> AnyValue
43
- { return Constants::UNDEFINED; },
44
- false,
45
- false);
416
+ return get_length_desc();
46
417
  }
47
418
 
48
419
  // --- charAt(pos) ---
49
420
  if (key == "charAt")
50
421
  {
51
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
52
- {
53
- double pos = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
54
- int index = static_cast<int>(pos);
55
- if (index < 0 || index >= self->value.length()) {
56
- return AnyValue::make_string("");
57
- }
58
- return AnyValue::make_string(std::string(1, self->value[index])); },
59
- key);
422
+ return get_charAt_fn();
60
423
  }
61
424
 
62
425
  // --- concat(str1, str2, ...) ---
63
426
  if (key == "concat")
64
427
  {
65
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
66
- {
67
- std::string result = self->value;
68
- for (const auto& arg : args)
69
- {
70
- result += arg.to_std_string();
71
- }
72
- return AnyValue::make_string(result); },
73
- key);
428
+ return get_concat_fn();
74
429
  }
75
430
 
76
431
  // --- endsWith(searchString, endPosition) ---
77
432
  if (key == "endsWith")
78
433
  {
79
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
80
- {
81
- if(args.empty()) return Constants::FALSE;
82
- std::string search = args[0].to_std_string();
83
- size_t end_pos = (args.size() > 1 && !args[1].is_undefined()) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : self->value.length();
84
-
85
- if (end_pos > self->value.length()) end_pos = self->value.length();
86
- if (search.length() > end_pos) return Constants::FALSE;
87
-
88
- return AnyValue::make_boolean(self->value.substr(end_pos - search.length(), search.length()) == search); },
89
- key);
434
+ return get_endsWith_fn();
90
435
  }
91
436
 
92
437
  // --- includes(searchString, position) ---
93
438
  if (key == "includes")
94
439
  {
95
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
96
- {
97
- if(args.empty()) return Constants::FALSE;
98
- std::string search = args[0].to_std_string();
99
- size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
100
-
101
- return AnyValue::make_boolean(self->value.find(search, pos) != std::string::npos); },
102
- key);
440
+ return get_includes_fn();
103
441
  }
104
442
 
105
443
  // --- indexOf(searchString, position) ---
106
444
  if (key == "indexOf")
107
445
  {
108
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
109
- {
110
- if (args.empty()) return AnyValue::make_number(-1);
111
- std::string search = args[0].to_std_string();
112
- size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
113
- size_t result = self->value.find(search, pos);
114
- return result == std::string::npos ? AnyValue::make_number(-1) : AnyValue::make_number(result); },
115
- key);
446
+ return get_indexOf_fn();
116
447
  }
117
448
 
118
449
  // --- lastIndexOf(searchString, position) ---
119
450
  if (key == "lastIndexOf")
120
451
  {
121
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
122
- {
123
- if (args.empty()) return AnyValue::make_number(-1);
124
- std::string search = args[0].to_std_string();
125
- size_t pos = (args.size() > 1 && !args[1].is_undefined()) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : std::string::npos;
126
- size_t result = self->value.rfind(search, pos);
127
- return result == std::string::npos ? AnyValue::make_number(-1) : AnyValue::make_number(result); },
128
- key);
452
+ return get_lastIndexOf_fn();
129
453
  }
130
454
 
131
455
  // --- padEnd(targetLength, padString) ---
132
456
  if (key == "padEnd")
133
457
  {
134
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
135
- {
136
- size_t target_length = args.empty() ? 0 : static_cast<size_t>(Operators_Private::ToNumber(args[0]));
137
- if (self->value.length() >= target_length) return AnyValue::make_string(self->value);
138
- std::string pad_string = (args.size() > 1 && !args[1].is_undefined() && !args[1].to_std_string().empty()) ? args[1].to_std_string() : " ";
139
- std::string result = self->value;
140
- while (result.length() < target_length)
141
- {
142
- result += pad_string;
143
- }
144
- return AnyValue::make_string(result.substr(0, target_length)); },
145
- key);
458
+ return get_padEnd_fn();
146
459
  }
147
460
 
148
461
  // --- padStart(targetLength, padString) ---
149
462
  if (key == "padStart")
150
463
  {
151
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
152
- {
153
- size_t target_length = args.empty() ? 0 : static_cast<size_t>(Operators_Private::ToNumber(args[0]));
154
- if (self->value.length() >= target_length) return AnyValue::make_string(self->value);
155
- std::string pad_string = (args.size() > 1 && !args[1].is_undefined() && !args[1].to_std_string().empty()) ? args[1].to_std_string() : " ";
156
- std::string padding;
157
- while (padding.length() < target_length - self->value.length())
158
- {
159
- padding += pad_string;
160
- }
161
- return AnyValue::make_string(padding.substr(0, target_length - self->value.length()) + self->value); },
162
- key);
464
+ return get_padStart_fn();
163
465
  }
164
466
 
165
467
  // --- repeat(count) ---
166
468
  if (key == "repeat")
167
469
  {
168
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
169
- {
170
- double count = args.empty() ? 0 : Operators_Private::ToNumber(args[0]);
171
- if (count < 0) {
172
- // In a real implementation, this should throw a RangeError.
173
- return AnyValue::make_string("");
174
- }
175
- std::string result = "";
176
- for (int i = 0; i < count; ++i)
177
- {
178
- result += self->value;
179
- }
180
- return AnyValue::make_string(result); },
181
- key);
470
+ return get_repeat_fn();
182
471
  }
183
472
 
184
473
  // --- replace(substr, newSubstr) ---
185
474
  if (key == "replace")
186
475
  {
187
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
188
- {
189
- if (args.size() < 2) return AnyValue::make_string(self->value);
190
- std::string search = args[0].to_std_string();
191
- std::string replacement = args[1].to_std_string();
192
- std::string result = self->value;
193
- size_t pos = result.find(search);
194
- if (pos != std::string::npos)
195
- {
196
- result.replace(pos, search.length(), replacement);
197
- }
198
- return AnyValue::make_string(result); },
199
- key);
476
+ return get_replace_fn();
200
477
  }
201
478
 
202
479
  // --- replaceAll(substr, newSubstr) ---
203
480
  if (key == "replaceAll")
204
481
  {
205
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
206
- {
207
- if (args.size() < 2) return AnyValue::make_string(self->value);
208
- std::string search = args[0].to_std_string();
209
- if (search.empty()) return AnyValue::make_string(self->value);
210
- std::string replacement = args[1].to_std_string();
211
- std::string result = self->value;
212
- size_t pos = result.find(search);
213
- while (pos != std::string::npos)
214
- {
215
- result.replace(pos, search.length(), replacement);
216
- pos = result.find(search, pos + replacement.length());
217
- }
218
- return AnyValue::make_string(result); },
219
- key);
482
+ return get_replaceAll_fn();
220
483
  }
221
484
 
222
485
  // --- slice(beginIndex, endIndex) ---
223
486
  if (key == "slice")
224
487
  {
225
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
226
- {
227
- int len = self->value.length();
228
- int start = args.empty() ? 0 : Operators_Private::ToInt32(args[0]);
229
- int end = (args.size() < 2 || args[1].is_undefined()) ? len : Operators_Private::ToInt32(args[1]);
230
-
231
- if (start < 0) start += len;
232
- if (end < 0) end += len;
233
-
234
- start = std::max(0, std::min(len, start));
235
- end = std::max(0, std::min(len, end));
236
-
237
- if (start >= end) return AnyValue::make_string("");
238
- return AnyValue::make_string(self->value.substr(start, end - start)); },
239
- key);
488
+ return get_slice_fn();
240
489
  }
241
490
 
242
491
  // --- split(separator) ---
243
492
  if (key == "split")
244
493
  {
245
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
246
- {
247
- std::string separator = (args.empty() || args[0].is_undefined()) ? "" : args[0].to_std_string();
248
- std::vector<jspp::AnyValue> result_vec;
249
-
250
- if (separator.empty()) {
251
- for (char c : (self->value)) {
252
- result_vec.push_back(AnyValue::make_string(std::string(1, c)));
253
- }
254
- } else {
255
- std::string temp = (self->value);
256
- size_t pos = 0;
257
- while ((pos = temp.find(separator)) != std::string::npos) {
258
- result_vec.push_back(AnyValue::make_string(temp.substr(0, pos)));
259
- temp.erase(0, pos + separator.length());
260
- }
261
- result_vec.push_back(AnyValue::make_string(temp));
262
- }
263
- return AnyValue::make_array(std::move(result_vec)); },
264
- key);
494
+ return get_split_fn();
265
495
  }
266
496
 
267
497
  // --- startsWith(searchString, position) ---
268
498
  if (key == "startsWith")
269
499
  {
270
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
271
- {
272
- if(args.empty()) return Constants::FALSE;
273
- std::string search = args[0].to_std_string();
274
- size_t pos = (args.size() > 1) ? static_cast<size_t>(Operators_Private::ToNumber(args[1])) : 0;
275
- if (pos > self->value.length()) pos = self->value.length();
276
-
277
- return AnyValue::make_boolean(self->value.rfind(search, pos) == pos); },
278
- key);
500
+ return get_startsWith_fn();
279
501
  }
280
502
 
281
503
  // --- substring(indexStart, indexEnd) ---
282
504
  if (key == "substring")
283
505
  {
284
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
285
- {
286
- int len = self->value.length();
287
- int start = args.empty() ? 0 : Operators_Private::ToInt32(args[0]);
288
- int end = (args.size() < 2 || args[1].is_undefined()) ? len : Operators_Private::ToInt32(args[1]);
289
-
290
- start = std::max(0, start);
291
- end = std::max(0, end);
292
-
293
- if (start > end) std::swap(start, end);
294
-
295
- start = std::min(len, start);
296
- end = std::min(len, end);
297
-
298
- return AnyValue::make_string(self->value.substr(start, end - start)); },
299
- key);
506
+ return get_substring_fn();
300
507
  }
301
508
 
302
509
  // --- toLowerCase() ---
303
510
  if (key == "toLowerCase")
304
511
  {
305
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
306
- {
307
- std::string result = self->value;
308
- std::transform(result.begin(), result.end(), result.begin(),
309
- [](unsigned char c){ return std::tolower(c); });
310
- return AnyValue::make_string(result); },
311
- key);
512
+ return get_toLowerCase_fn();
312
513
  }
313
514
 
314
515
  // --- toUpperCase() ---
315
516
  if (key == "toUpperCase")
316
517
  {
317
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
318
- {
319
- std::string result = self->value;
320
- std::transform(result.begin(), result.end(), result.begin(),
321
- [](unsigned char c){ return std::toupper(c); });
322
- return AnyValue::make_string(result); },
323
- key);
518
+ return get_toUpperCase_fn();
324
519
  }
325
520
 
326
521
  // --- trim() ---
327
522
  if (key == "trim")
328
523
  {
329
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
330
- {
331
- const char* whitespace = " \t\n\r\f\v";
332
- std::string result = self->value;
333
- result.erase(0, result.find_first_not_of(whitespace));
334
- result.erase(result.find_last_not_of(whitespace) + 1);
335
- return AnyValue::make_string(result); },
336
- key);
524
+ return get_trim_fn();
337
525
  }
338
526
 
339
527
  // --- trimEnd() ---
340
528
  if (key == "trimEnd")
341
529
  {
342
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
343
- {
344
- const char* whitespace = " \t\n\r\f\v";
345
- std::string result = self->value;
346
- result.erase(result.find_last_not_of(whitespace) + 1);
347
- return AnyValue::make_string(result); },
348
- key);
530
+ return get_trimEnd_fn();
349
531
  }
350
532
 
351
533
  // --- trimStart() ---
352
534
  if (key == "trimStart")
353
535
  {
354
- return AnyValue::make_function([self](const AnyValue &thisVal, std::span<const AnyValue> args) -> AnyValue
355
- {
356
- const char* whitespace = " \t\n\r\f\v";
357
- std::string result = self->value;
358
- result.erase(0, result.find_first_not_of(whitespace));
359
- return AnyValue::make_string(result); },
360
- key);
536
+ return get_trimStart_fn();
361
537
  }
362
538
 
363
539
  return std::nullopt;
364
540
  }
365
541
  }
366
- }
542
+ }