xbintsc 0.3.3 → 0.3.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.
- package/dist/src/ast/expressions.d.ts +8 -0
- package/dist/src/binder/binder.js +1 -0
- package/dist/src/binder/binder.js.map +1 -1
- package/dist/src/binder/references.d.ts +1 -1
- package/dist/src/binder/references.js +34 -5
- package/dist/src/binder/references.js.map +1 -1
- package/dist/src/binder/types.d.ts +4 -0
- package/dist/src/binder/types.js.map +1 -1
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/codegen/generator/calls/access.d.ts +9 -1
- package/dist/src/codegen/generator/calls/access.js +146 -13
- package/dist/src/codegen/generator/calls/access.js.map +1 -1
- package/dist/src/codegen/generator/calls/closures.d.ts +1 -0
- package/dist/src/codegen/generator/calls/closures.js +25 -0
- package/dist/src/codegen/generator/calls/closures.js.map +1 -1
- package/dist/src/codegen/generator/calls/invocation.js +12 -1
- package/dist/src/codegen/generator/calls/invocation.js.map +1 -1
- package/dist/src/codegen/generator/calls/literals.js +12 -4
- package/dist/src/codegen/generator/calls/literals.js.map +1 -1
- package/dist/src/codegen/generator/calls/super.js +4 -7
- package/dist/src/codegen/generator/calls/super.js.map +1 -1
- package/dist/src/codegen/generator/context.d.ts +21 -2
- package/dist/src/codegen/generator/context.js +42 -5
- package/dist/src/codegen/generator/context.js.map +1 -1
- package/dist/src/codegen/generator/expressions/assignment.js +1 -3
- package/dist/src/codegen/generator/expressions/assignment.js.map +1 -1
- package/dist/src/codegen/generator/expressions/primary.d.ts +3 -1
- package/dist/src/codegen/generator/expressions/primary.js +99 -1
- package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
- package/dist/src/codegen/generator/generator.js.map +1 -1
- package/dist/src/codegen/generator/module.js +25 -15
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/state.d.ts +15 -0
- package/dist/src/codegen/generator/state.js +28 -1
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/statements/control-flow.d.ts +3 -1
- package/dist/src/codegen/generator/statements/control-flow.js +85 -0
- package/dist/src/codegen/generator/statements/control-flow.js.map +1 -1
- package/dist/src/codegen/generator/statements/dispatch.js +15 -6
- package/dist/src/codegen/generator/statements/dispatch.js.map +1 -1
- package/dist/src/codegen/generator/statements/loops.d.ts +3 -0
- package/dist/src/codegen/generator/statements/loops.js +25 -11
- package/dist/src/codegen/generator/statements/loops.js.map +1 -1
- package/dist/src/codegen/generator/tables.d.ts +7 -0
- package/dist/src/codegen/generator/tables.js +41 -1
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/driver/compiler.d.ts +1 -1
- package/dist/src/driver/compiler.js +33 -1
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/modules.d.ts +4 -3
- package/dist/src/driver/modules.js +61 -4
- package/dist/src/driver/modules.js.map +1 -1
- package/dist/src/driver/toolchain.js +1 -1
- package/dist/src/driver/toolchain.js.map +1 -1
- package/dist/src/lexer/scanner.js.map +1 -1
- package/dist/src/parser/declarations/classes.js +4 -0
- package/dist/src/parser/declarations/classes.js.map +1 -1
- package/dist/src/parser/declarations/type-members.js.map +1 -1
- package/dist/src/parser/expressions.d.ts +2 -1
- package/dist/src/parser/expressions.js +10 -1
- package/dist/src/parser/expressions.js.map +1 -1
- package/dist/src/parser/helpers.js +2 -2
- package/dist/src/parser/helpers.js.map +1 -1
- package/dist/src/parser/literals.js +79 -6
- package/dist/src/parser/literals.js.map +1 -1
- package/dist/src/parser/modules.js.map +1 -1
- package/dist/src/parser/parser.js +0 -1
- package/dist/src/parser/parser.js.map +1 -1
- package/dist/src/parser/statements.d.ts +1 -0
- package/dist/src/parser/statements.js +13 -1
- package/dist/src/parser/statements.js.map +1 -1
- package/dist/src/parser/types.js +2 -2
- package/dist/src/parser/types.js.map +1 -1
- package/dist/tests/ast/factory.test.d.ts +1 -0
- package/dist/tests/ast/factory.test.js +35 -0
- package/dist/tests/ast/factory.test.js.map +1 -0
- package/dist/tests/ast/visitor.test.d.ts +1 -0
- package/dist/tests/ast/visitor.test.js +53 -0
- package/dist/tests/ast/visitor.test.js.map +1 -0
- package/dist/tests/cli/main.test.js +109 -9
- package/dist/tests/cli/main.test.js.map +1 -1
- package/dist/tests/codegen/closures.test.d.ts +1 -0
- package/dist/tests/codegen/closures.test.js +32 -0
- package/dist/tests/codegen/closures.test.js.map +1 -0
- package/dist/tests/codegen/expressions.test.d.ts +1 -0
- package/dist/tests/codegen/expressions.test.js +149 -0
- package/dist/tests/codegen/expressions.test.js.map +1 -0
- package/dist/tests/codegen/llvm.test.js +14 -0
- package/dist/tests/codegen/llvm.test.js.map +1 -1
- package/dist/tests/codegen/values.test.d.ts +1 -0
- package/dist/tests/codegen/values.test.js +48 -0
- package/dist/tests/codegen/values.test.js.map +1 -0
- package/dist/tests/diagnostics/diagnostic.test.d.ts +1 -0
- package/dist/tests/diagnostics/diagnostic.test.js +117 -0
- package/dist/tests/diagnostics/diagnostic.test.js.map +1 -0
- package/dist/tests/diagnostics/source.test.d.ts +1 -0
- package/dist/tests/diagnostics/source.test.js +58 -0
- package/dist/tests/diagnostics/source.test.js.map +1 -0
- package/dist/tests/driver/modules.test.d.ts +1 -0
- package/dist/tests/driver/modules.test.js +140 -0
- package/dist/tests/driver/modules.test.js.map +1 -0
- package/dist/tests/driver/paths.test.js +17 -1
- package/dist/tests/driver/paths.test.js.map +1 -1
- package/dist/tests/driver/runtime-lib.test.d.ts +1 -0
- package/dist/tests/driver/runtime-lib.test.js +19 -0
- package/dist/tests/driver/runtime-lib.test.js.map +1 -0
- package/dist/tests/driver/toolchain-provider.test.js +91 -0
- package/dist/tests/driver/toolchain-provider.test.js.map +1 -1
- package/dist/tests/driver/toolchain.test.js +11 -1
- package/dist/tests/driver/toolchain.test.js.map +1 -1
- package/dist/tests/e2e/compile-node.test.js +14 -1
- package/dist/tests/e2e/compile-node.test.js.map +1 -1
- package/dist/tests/e2e/compile.test.js +465 -2
- package/dist/tests/e2e/compile.test.js.map +1 -1
- package/dist/tests/e2e/differential.test.d.ts +7 -0
- package/dist/tests/e2e/differential.test.js +581 -0
- package/dist/tests/e2e/differential.test.js.map +1 -0
- package/dist/tests/e2e/harness.d.ts +21 -0
- package/dist/tests/e2e/harness.js +26 -0
- package/dist/tests/e2e/harness.js.map +1 -1
- package/dist/tests/extensions/node.test.d.ts +1 -0
- package/dist/tests/extensions/node.test.js +32 -0
- package/dist/tests/extensions/node.test.js.map +1 -0
- package/dist/tests/lexer/identifiers.test.d.ts +1 -0
- package/dist/tests/lexer/identifiers.test.js +13 -0
- package/dist/tests/lexer/identifiers.test.js.map +1 -0
- package/dist/tests/lexer/numbers.test.d.ts +1 -0
- package/dist/tests/lexer/numbers.test.js +23 -0
- package/dist/tests/lexer/numbers.test.js.map +1 -0
- package/dist/tests/lexer/strings.test.d.ts +1 -0
- package/dist/tests/lexer/strings.test.js +72 -0
- package/dist/tests/lexer/strings.test.js.map +1 -0
- package/dist/tests/parser/declarations.test.d.ts +1 -0
- package/dist/tests/parser/declarations.test.js +70 -0
- package/dist/tests/parser/declarations.test.js.map +1 -0
- package/dist/tests/parser/expressions.test.d.ts +1 -0
- package/dist/tests/parser/expressions.test.js +47 -0
- package/dist/tests/parser/expressions.test.js.map +1 -0
- package/dist/tests/parser/helpers.test.d.ts +1 -0
- package/dist/tests/parser/helpers.test.js +58 -0
- package/dist/tests/parser/helpers.test.js.map +1 -0
- package/dist/tests/parser/literals.test.d.ts +1 -0
- package/dist/tests/parser/literals.test.js +70 -0
- package/dist/tests/parser/literals.test.js.map +1 -0
- package/dist/tests/parser/module-syntax.test.d.ts +1 -0
- package/dist/tests/parser/module-syntax.test.js +91 -0
- package/dist/tests/parser/module-syntax.test.js.map +1 -0
- package/dist/tests/parser/statements.test.d.ts +1 -0
- package/dist/tests/parser/statements.test.js +85 -0
- package/dist/tests/parser/statements.test.js.map +1 -0
- package/dist/tests/parser/type-members.test.d.ts +1 -0
- package/dist/tests/parser/type-members.test.js +86 -0
- package/dist/tests/parser/type-members.test.js.map +1 -0
- package/dist/tests/parser/types.test.d.ts +1 -0
- package/dist/tests/parser/types.test.js +143 -0
- package/dist/tests/parser/types.test.js.map +1 -0
- package/package.json +6 -1
- package/runtime/ext_node/fs/fs_ops.c +36 -1
- package/runtime/rt.h +17 -0
- package/runtime/rt_internal.h +88 -2
- package/runtime/xt_builtins.c +174 -6
- package/runtime/xt_containers.c +234 -42
- package/runtime/xt_generator.c +304 -0
- package/runtime/xt_io.c +170 -30
- package/runtime/xt_promise.c +6 -1
- package/runtime/xt_regex.h +105 -35
- package/runtime/xt_stdlib/dispatch.inc +255 -4
- package/runtime/xt_stdlib/strings.inc +17 -13
- package/runtime/xt_stdlib2/arrays.inc +126 -19
- package/runtime/xt_stdlib2/date.inc +9 -2
- package/runtime/xt_stdlib2/error.inc +162 -12
- package/runtime/xt_stdlib2/helpers.inc +4 -0
- package/runtime/xt_stdlib2/json.inc +19 -6
- package/runtime/xt_stdlib2/number-string-statics.inc +1 -1
- package/runtime/xt_stdlib2/numbers.inc +4 -5
- package/runtime/xt_stdlib2/objects.inc +29 -0
- package/runtime/xt_stdlib2/regexp-match.inc +293 -51
- package/runtime/xt_stdlib2/set.inc +58 -2
- package/runtime/xt_stdlib2/strings.inc +38 -0
- package/runtime/xt_symbol.c +149 -0
- package/runtime/xt_values.c +221 -15
- package/scripts/build-runtime.ts +1 -1
- package/src/ast/expressions.ts +8 -0
- package/src/binder/binder.ts +1 -1
- package/src/binder/references.ts +47 -4
- package/src/binder/types.ts +4 -0
- package/src/cli/main.ts +1 -2
- package/src/codegen/generator/calls/access.ts +158 -13
- package/src/codegen/generator/calls/closures.ts +24 -0
- package/src/codegen/generator/calls/invocation.ts +11 -1
- package/src/codegen/generator/calls/literals.ts +10 -4
- package/src/codegen/generator/calls/super.ts +6 -9
- package/src/codegen/generator/context.ts +44 -7
- package/src/codegen/generator/expressions/assignment.ts +1 -3
- package/src/codegen/generator/expressions/primary.ts +108 -2
- package/src/codegen/generator/generator.ts +0 -1
- package/src/codegen/generator/module.ts +24 -18
- package/src/codegen/generator/state.ts +44 -1
- package/src/codegen/generator/statements/control-flow.ts +86 -0
- package/src/codegen/generator/statements/dispatch.ts +18 -6
- package/src/codegen/generator/statements/loops.ts +29 -11
- package/src/codegen/generator/tables.ts +44 -1
- package/src/driver/compiler.ts +32 -2
- package/src/driver/modules.ts +64 -4
- package/src/driver/toolchain.ts +1 -1
- package/src/lexer/scanner.ts +0 -1
- package/src/parser/declarations/classes.ts +4 -0
- package/src/parser/declarations/type-members.ts +0 -2
- package/src/parser/expressions.ts +13 -1
- package/src/parser/helpers.ts +2 -2
- package/src/parser/literals.ts +82 -7
- package/src/parser/modules.ts +0 -1
- package/src/parser/parser.ts +0 -1
- package/src/parser/statements.ts +14 -0
- package/src/parser/types.ts +2 -2
|
@@ -33,33 +33,63 @@ static xt_value xt_array_quantifier(xt_value value, xt_value fn, int every) {
|
|
|
33
33
|
return xt_bool(every ? 1 : 0);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
/*
|
|
37
|
+
* Default `Array.prototype.sort` comparator. Per spec the elements are
|
|
38
|
+
* converted to strings and compared by UTF-16 code unit; `undefined` always
|
|
39
|
+
* sorts last and holes are handled by the caller. Because our strings are
|
|
40
|
+
* UTF-8, a byte-wise compare matches UTF-16 ordering for the BMP (and differs
|
|
41
|
+
* only for supplementary vs. U+E000..U+FFFF code points).
|
|
42
|
+
*/
|
|
43
|
+
static int xt_array_default_compare(xt_value a, xt_value b) {
|
|
44
|
+
if (a == XT_UNDEFINED) return b == XT_UNDEFINED ? 0 : 1;
|
|
45
|
+
if (b == XT_UNDEFINED) return -1;
|
|
46
|
+
xt_string *sa = xt_as_string(xt_to_string(a));
|
|
47
|
+
xt_string *sb = xt_as_string(xt_to_string(b));
|
|
48
|
+
uint32_t n = sa->length < sb->length ? sa->length : sb->length;
|
|
49
|
+
int cmp = n ? memcmp(sa->data, sb->data, n) : 0;
|
|
50
|
+
if (cmp != 0) return cmp < 0 ? -1 : 1;
|
|
51
|
+
if (sa->length == sb->length) return 0;
|
|
52
|
+
return sa->length < sb->length ? -1 : 1;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static int xt_array_sort_compare(xt_value fn, int hasFn, xt_value a, xt_value b) {
|
|
56
|
+
if (!hasFn) return xt_array_default_compare(a, b);
|
|
57
|
+
xt_value args[2] = {a, b};
|
|
58
|
+
double result = xt_to_number(xt_closure_call(fn, 2, args));
|
|
59
|
+
if (result < 0) return -1;
|
|
60
|
+
if (result > 0) return 1;
|
|
39
61
|
return 0;
|
|
40
62
|
}
|
|
41
63
|
|
|
64
|
+
/* Stable bottom-up merge sort: O(n log n) and never reorders equal keys. */
|
|
65
|
+
static void xt_array_merge_sort(xt_value *items, xt_value *scratch, uint32_t length, xt_value fn, int hasFn) {
|
|
66
|
+
for (uint32_t width = 1; width < length; width *= 2) {
|
|
67
|
+
for (uint32_t lo = 0; lo < length; lo += 2 * width) {
|
|
68
|
+
uint32_t mid = lo + width < length ? lo + width : length;
|
|
69
|
+
uint32_t hi = lo + 2 * width < length ? lo + 2 * width : length;
|
|
70
|
+
uint32_t i = lo, j = mid, k = lo;
|
|
71
|
+
while (i < mid && j < hi) {
|
|
72
|
+
if (xt_array_sort_compare(fn, hasFn, items[j], items[i]) < 0) scratch[k++] = items[j++];
|
|
73
|
+
else scratch[k++] = items[i++];
|
|
74
|
+
}
|
|
75
|
+
while (i < mid) scratch[k++] = items[i++];
|
|
76
|
+
while (j < hi) scratch[k++] = items[j++];
|
|
77
|
+
for (k = lo; k < hi; k++) items[k] = scratch[k];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
42
82
|
static xt_value xt_array_sort(xt_value value, xt_value fn) {
|
|
43
83
|
xt_array *array = xt_as_array(value);
|
|
44
84
|
if (!array || array->length < 2) return value;
|
|
45
85
|
int hasFn = XT_IS_FUNCTION(fn);
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
int cmp;
|
|
51
|
-
if (hasFn) {
|
|
52
|
-
xt_value args[2] = {array->items[j], key};
|
|
53
|
-
cmp = (int)xt_to_number(xt_closure_call(fn, 2, args));
|
|
54
|
-
} else {
|
|
55
|
-
cmp = xt_array_compare_values(array->items[j], key);
|
|
56
|
-
}
|
|
57
|
-
if (cmp <= 0) break;
|
|
58
|
-
array->items[j + 1] = array->items[j];
|
|
59
|
-
j--;
|
|
60
|
-
}
|
|
61
|
-
array->items[j + 1] = key;
|
|
86
|
+
xt_value *scratch = (xt_value *)malloc(sizeof(xt_value) * array->length);
|
|
87
|
+
if (!scratch) {
|
|
88
|
+
xt_throw(xt_string_from_cstr("RangeError: out of memory in Array.prototype.sort"));
|
|
89
|
+
return value;
|
|
62
90
|
}
|
|
91
|
+
xt_array_merge_sort(array->items, scratch, array->length, fn, hasFn);
|
|
92
|
+
free(scratch);
|
|
63
93
|
return value;
|
|
64
94
|
}
|
|
65
95
|
|
|
@@ -130,6 +160,78 @@ static xt_value xt_array_copy_within(xt_value value, xt_value targetValue, xt_va
|
|
|
130
160
|
return value;
|
|
131
161
|
}
|
|
132
162
|
|
|
163
|
+
static xt_value xt_array_splice(xt_value value, int32_t argc, xt_value *argv) {
|
|
164
|
+
xt_array *array = xt_as_array(value);
|
|
165
|
+
if (!array) return XT_UNDEFINED;
|
|
166
|
+
int32_t len = (int32_t)array->length;
|
|
167
|
+
int32_t start = argc >= 1 ? xt_to_int32(argv[0]) : 0;
|
|
168
|
+
if (start < 0) start += len;
|
|
169
|
+
if (start < 0) start = 0;
|
|
170
|
+
if (start > len) start = len;
|
|
171
|
+
int32_t deleteCount;
|
|
172
|
+
if (argc < 2) {
|
|
173
|
+
deleteCount = len - start;
|
|
174
|
+
} else {
|
|
175
|
+
deleteCount = xt_to_int32(argv[1]);
|
|
176
|
+
if (deleteCount < 0) deleteCount = 0;
|
|
177
|
+
if (deleteCount > len - start) deleteCount = len - start;
|
|
178
|
+
}
|
|
179
|
+
int32_t insertCount = argc > 2 ? argc - 2 : 0;
|
|
180
|
+
xt_value removed = xt_array_new(deleteCount, deleteCount > 0 ? array->items + start : NULL);
|
|
181
|
+
int32_t newLength = len - deleteCount + insertCount;
|
|
182
|
+
xt_array_reserve(array, (uint32_t)(newLength > 0 ? newLength : 0));
|
|
183
|
+
if (insertCount != deleteCount) {
|
|
184
|
+
memmove(array->items + start + insertCount, array->items + start + deleteCount,
|
|
185
|
+
sizeof(xt_value) * (size_t)(len - start - deleteCount));
|
|
186
|
+
}
|
|
187
|
+
for (int32_t i = 0; i < insertCount; i++) array->items[start + i] = argv[2 + i];
|
|
188
|
+
array->length = (uint32_t)newLength;
|
|
189
|
+
return removed;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* Copy the own elements of `value` into a fresh array. */
|
|
193
|
+
static xt_value xt_array_copy(xt_value value) {
|
|
194
|
+
xt_value out = xt_array_new(0, NULL);
|
|
195
|
+
xt_array *array = xt_as_array(value);
|
|
196
|
+
if (!array) return out;
|
|
197
|
+
for (uint32_t i = 0; i < array->length; i++) xt_array_push(out, array->items[i]);
|
|
198
|
+
return out;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
static xt_value xt_array_to_reversed(xt_value value) {
|
|
202
|
+
xt_value copy = xt_array_copy(value);
|
|
203
|
+
xt_array *array = xt_as_array(copy);
|
|
204
|
+
for (uint32_t i = 0; i + 1 < array->length - i; i++) {
|
|
205
|
+
xt_value tmp = array->items[i];
|
|
206
|
+
array->items[i] = array->items[array->length - 1 - i];
|
|
207
|
+
array->items[array->length - 1 - i] = tmp;
|
|
208
|
+
}
|
|
209
|
+
return copy;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
static xt_value xt_array_to_sorted(xt_value value, xt_value fn) {
|
|
213
|
+
return xt_array_sort(xt_array_copy(value), fn);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
static xt_value xt_array_to_spliced(xt_value value, int32_t argc, xt_value *argv) {
|
|
217
|
+
xt_value copy = xt_array_copy(value);
|
|
218
|
+
xt_array_splice(copy, argc, argv);
|
|
219
|
+
return copy;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
static xt_value xt_array_with(xt_value value, xt_value indexValue, xt_value newValue) {
|
|
223
|
+
xt_value copy = xt_array_copy(value);
|
|
224
|
+
xt_array *array = xt_as_array(copy);
|
|
225
|
+
int32_t index = xt_to_int32(indexValue);
|
|
226
|
+
if (index < 0) index += (int32_t)array->length;
|
|
227
|
+
if (index < 0 || index >= (int32_t)array->length) {
|
|
228
|
+
xt_throw(xt_add(xt_string_from_cstr("RangeError: Invalid index : "), xt_to_string(indexValue)));
|
|
229
|
+
return copy;
|
|
230
|
+
}
|
|
231
|
+
array->items[index] = newValue;
|
|
232
|
+
return copy;
|
|
233
|
+
}
|
|
234
|
+
|
|
133
235
|
xt_value xt_ext_array_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled) {
|
|
134
236
|
*handled = 1;
|
|
135
237
|
if (strcmp(method, "at") == 0) return xt_array_at(target, xt_arg_at(argc, argv, 0));
|
|
@@ -151,6 +253,11 @@ xt_value xt_ext_array_method(xt_value target, const char *method, int32_t argc,
|
|
|
151
253
|
if (strcmp(method, "lastIndexOf") == 0) return xt_array_last_index_of(target, xt_arg_at(argc, argv, 0), xt_arg_at(argc, argv, 1));
|
|
152
254
|
if (strcmp(method, "fill") == 0) return xt_array_fill(target, xt_arg_at(argc, argv, 0), xt_arg_at(argc, argv, 1), xt_arg_at(argc, argv, 2));
|
|
153
255
|
if (strcmp(method, "copyWithin") == 0) return xt_array_copy_within(target, xt_arg_at(argc, argv, 0), xt_arg_at(argc, argv, 1), xt_arg_at(argc, argv, 2));
|
|
256
|
+
if (strcmp(method, "splice") == 0) return xt_array_splice(target, argc, argv);
|
|
257
|
+
if (strcmp(method, "toReversed") == 0) return xt_array_to_reversed(target);
|
|
258
|
+
if (strcmp(method, "toSorted") == 0) return xt_array_to_sorted(target, xt_arg_at(argc, argv, 0));
|
|
259
|
+
if (strcmp(method, "toSpliced") == 0) return xt_array_to_spliced(target, argc, argv);
|
|
260
|
+
if (strcmp(method, "with") == 0) return xt_array_with(target, xt_arg_at(argc, argv, 0), xt_arg_at(argc, argv, 1));
|
|
154
261
|
if (strcmp(method, "reduceRight") == 0) {
|
|
155
262
|
xt_array *array = xt_as_array(target);
|
|
156
263
|
if (!array) return XT_UNDEFINED;
|
|
@@ -40,18 +40,25 @@ xt_value xt_date_static(xt_value name, int32_t argc, xt_value *argv) {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
static xt_value xt_date_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled) {
|
|
43
|
+
(void)argc;
|
|
44
|
+
(void)argv;
|
|
43
45
|
*handled = 1;
|
|
44
46
|
xt_date *date = (xt_date *)XT_GET_PTR(target);
|
|
47
|
+
if (strcmp(method, "getTime") == 0 || strcmp(method, "valueOf") == 0) return xt_number(date->time);
|
|
45
48
|
time_t seconds = (time_t)(date->time / 1000.0);
|
|
46
49
|
struct tm tm;
|
|
47
|
-
xt_gmtime_r(&seconds, &tm);
|
|
48
|
-
if (strcmp(method, "getTime") == 0 || strcmp(method, "valueOf") == 0) return xt_number(date->time);
|
|
49
50
|
const char *name = method;
|
|
50
51
|
char utc[32];
|
|
52
|
+
int isUtc = 0;
|
|
51
53
|
if (strncmp(method, "getUTC", 6) == 0) {
|
|
52
54
|
snprintf(utc, sizeof(utc), "get%s", method + 6);
|
|
53
55
|
name = utc;
|
|
56
|
+
isUtc = 1;
|
|
54
57
|
}
|
|
58
|
+
/* Bare getters and `toString` report local time; `getUTC*` and
|
|
59
|
+
* `toISOString` report UTC. */
|
|
60
|
+
if (isUtc || strcmp(method, "toISOString") == 0) xt_gmtime_r(&seconds, &tm);
|
|
61
|
+
else xt_localtime_r(&seconds, &tm);
|
|
55
62
|
if (strcmp(name, "getFullYear") == 0) return xt_number(tm.tm_year + 1900);
|
|
56
63
|
if (strcmp(name, "getMonth") == 0) return xt_number(tm.tm_mon);
|
|
57
64
|
if (strcmp(name, "getDate") == 0) return xt_number(tm.tm_mday);
|
|
@@ -1,21 +1,171 @@
|
|
|
1
|
-
|
|
1
|
+
/* ------------------------------------------------------------------------- */
|
|
2
|
+
/* Error family: prototype chain, first-class constructors and formatting. */
|
|
3
|
+
|
|
4
|
+
/* Every constructor in the Error family shares one implementation; the name
|
|
5
|
+
* is what distinguishes them. Prototypes chain `TypeError.prototype` (etc.)
|
|
6
|
+
* to `Error.prototype`, so `instanceof Error` succeeds for every member. */
|
|
7
|
+
static const char *const XT_ERROR_NAMES[] = {
|
|
8
|
+
"Error", "TypeError", "RangeError", "SyntaxError",
|
|
9
|
+
"ReferenceError", "EvalError", "URIError", "AggregateError",
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
static int xt_error_is_family(const char *name) {
|
|
13
|
+
for (size_t i = 0; i < sizeof(XT_ERROR_NAMES) / sizeof(XT_ERROR_NAMES[0]); i++) {
|
|
14
|
+
if (strcmp(name, XT_ERROR_NAMES[i]) == 0) return 1;
|
|
15
|
+
}
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static xt_value xt_error_root_proto = XT_UNDEFINED;
|
|
20
|
+
|
|
21
|
+
static xt_value xt_error_proto_for(const char *name) {
|
|
22
|
+
if (!XT_IS_OBJECT(xt_error_root_proto)) {
|
|
23
|
+
xt_error_root_proto = xt_object_new();
|
|
24
|
+
xt_object_set(xt_error_root_proto, xt_string_from_cstr("name"),
|
|
25
|
+
xt_string_from_cstr("Error"));
|
|
26
|
+
xt_object_set(xt_error_root_proto, xt_string_from_cstr("message"),
|
|
27
|
+
xt_string_from_cstr(""));
|
|
28
|
+
}
|
|
29
|
+
if (strcmp(name, "Error") == 0) return xt_error_root_proto;
|
|
30
|
+
xt_value key = xt_string_from_cstr(name);
|
|
31
|
+
xt_value registry = xt_object_get(xt_error_root_proto, xt_string_from_cstr("__children"));
|
|
32
|
+
if (!XT_IS_OBJECT(registry)) {
|
|
33
|
+
registry = xt_object_new();
|
|
34
|
+
xt_object_set(xt_error_root_proto, xt_string_from_cstr("__children"), registry);
|
|
35
|
+
}
|
|
36
|
+
xt_value existing = xt_object_get(registry, key);
|
|
37
|
+
if (XT_IS_OBJECT(existing)) return existing;
|
|
38
|
+
xt_value proto = xt_object_new();
|
|
39
|
+
xt_object_set_prototype(proto, xt_error_root_proto);
|
|
40
|
+
xt_object_set(proto, xt_string_from_cstr("name"), key);
|
|
41
|
+
xt_object_set(proto, xt_string_from_cstr("message"), xt_string_from_cstr(""));
|
|
42
|
+
xt_object_set(registry, key, proto);
|
|
43
|
+
return proto;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
xt_value xt_error_prototype(xt_value nameValue) {
|
|
47
|
+
const char *name = XT_IS_STRING(nameValue) ? xt_string_data(nameValue) : "Error";
|
|
48
|
+
if (!xt_error_is_family(name)) name = "Error";
|
|
49
|
+
return xt_error_proto_for(name);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static xt_value xt_make_error(const char *name, int32_t argc, xt_value *argv) {
|
|
53
|
+
if (!xt_error_is_family(name)) name = "Error";
|
|
2
54
|
xt_value error = xt_object_new();
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
55
|
+
((xt_object *)XT_GET_PTR(error))->header.kind = XT_OBJECT_KIND_ERROR;
|
|
56
|
+
xt_object_set_prototype(error, xt_error_proto_for(name));
|
|
57
|
+
xt_value message;
|
|
58
|
+
if (strcmp(name, "AggregateError") == 0) {
|
|
59
|
+
xt_value errors = xt_arg_at(argc, argv, 0);
|
|
60
|
+
xt_object_set(error, xt_string_from_cstr("errors"),
|
|
61
|
+
errors == XT_UNDEFINED ? xt_array_new(0, NULL) : errors);
|
|
62
|
+
message = xt_arg_at(argc, argv, 1);
|
|
63
|
+
} else {
|
|
64
|
+
message = xt_arg_at(argc, argv, 0);
|
|
65
|
+
}
|
|
66
|
+
xt_object_set(error, xt_string_from_cstr("name"), xt_string_from_cstr(name));
|
|
7
67
|
xt_object_set(error, xt_string_from_cstr("message"),
|
|
8
68
|
message == XT_UNDEFINED ? xt_string_from_cstr("") : message);
|
|
9
69
|
return error;
|
|
10
70
|
}
|
|
11
71
|
|
|
12
|
-
|
|
13
|
-
*
|
|
14
|
-
|
|
15
|
-
xt_value name =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
72
|
+
static xt_value xt_error_ctor_invoke(xt_value thisValue, xt_value env, int32_t argc,
|
|
73
|
+
xt_value *argv) {
|
|
74
|
+
(void)thisValue;
|
|
75
|
+
xt_value name = xt_closure_env(env, 0);
|
|
76
|
+
return xt_make_error(xt_string_data(name), argc, argv);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* The first-class value of a family constructor (used by `instanceof`,
|
|
80
|
+
* `typeof`, and `class X extends Error`). Cached on the prototype. */
|
|
81
|
+
xt_value xt_error_constructor(xt_value nameValue) {
|
|
82
|
+
const char *name = XT_IS_STRING(nameValue) ? xt_string_data(nameValue) : "Error";
|
|
83
|
+
if (!xt_error_is_family(name)) name = "Error";
|
|
84
|
+
xt_value proto = xt_error_proto_for(name);
|
|
85
|
+
xt_value key = xt_string_from_cstr("__ctor");
|
|
86
|
+
/* Own-property lookup only: a prototype walk would find `Error`'s
|
|
87
|
+
* constructor (stored on the root prototype) for every child. */
|
|
88
|
+
xt_property *existing =
|
|
89
|
+
xt_object_find_property((xt_object *)XT_GET_PTR(proto), key);
|
|
90
|
+
if (existing && XT_IS_FUNCTION(existing->value)) return existing->value;
|
|
91
|
+
xt_value env[1];
|
|
92
|
+
env[0] = xt_string_from_cstr(name);
|
|
93
|
+
xt_value closure = xt_closure_new((void *)xt_error_ctor_invoke, 1, env);
|
|
94
|
+
xt_function_set_prototype(closure, proto);
|
|
95
|
+
xt_function_set_metadata(closure, env[0], 1);
|
|
96
|
+
xt_object_set(proto, key, closure);
|
|
97
|
+
return closure;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
xt_value xt_error_to_string(xt_value error) {
|
|
101
|
+
xt_value name = xt_object_get(error, xt_string_from_cstr("name"));
|
|
102
|
+
xt_value message = xt_object_get(error, xt_string_from_cstr("message"));
|
|
103
|
+
xt_value nameStr = name == XT_UNDEFINED ? xt_string_from_cstr("Error") : xt_to_string(name);
|
|
104
|
+
xt_value messageStr =
|
|
105
|
+
message == XT_UNDEFINED ? xt_string_from_cstr("") : xt_to_string(message);
|
|
106
|
+
xt_string *ns = xt_as_string(nameStr);
|
|
107
|
+
xt_string *ms = xt_as_string(messageStr);
|
|
108
|
+
if (ns->length == 0) return messageStr;
|
|
109
|
+
if (ms->length == 0) return nameStr;
|
|
110
|
+
size_t total = ns->length + 2 + ms->length;
|
|
111
|
+
char *buffer = (char *)malloc(total + 1);
|
|
112
|
+
memcpy(buffer, ns->data, ns->length);
|
|
113
|
+
buffer[ns->length] = ':';
|
|
114
|
+
buffer[ns->length + 1] = ' ';
|
|
115
|
+
memcpy(buffer + ns->length + 2, ms->data, ms->length);
|
|
116
|
+
buffer[total] = '\0';
|
|
117
|
+
xt_value result = xt_string_new(buffer, total);
|
|
118
|
+
free(buffer);
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
xt_value xt_error_ctor(int32_t argc, xt_value *argv) {
|
|
123
|
+
return xt_make_error("Error", argc, argv);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
xt_value xt_type_error_ctor(int32_t argc, xt_value *argv) {
|
|
127
|
+
return xt_make_error("TypeError", argc, argv);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
xt_value xt_range_error_ctor(int32_t argc, xt_value *argv) {
|
|
131
|
+
return xt_make_error("RangeError", argc, argv);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
xt_value xt_syntax_error_ctor(int32_t argc, xt_value *argv) {
|
|
135
|
+
return xt_make_error("SyntaxError", argc, argv);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
xt_value xt_reference_error_ctor(int32_t argc, xt_value *argv) {
|
|
139
|
+
return xt_make_error("ReferenceError", argc, argv);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
xt_value xt_eval_error_ctor(int32_t argc, xt_value *argv) {
|
|
143
|
+
return xt_make_error("EvalError", argc, argv);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
xt_value xt_uri_error_ctor(int32_t argc, xt_value *argv) {
|
|
147
|
+
return xt_make_error("URIError", argc, argv);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
xt_value xt_aggregate_error_ctor(int32_t argc, xt_value *argv) {
|
|
151
|
+
return xt_make_error("AggregateError", argc, argv);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* `super(message)` inside a subclass of the builtin Error family: initialize
|
|
155
|
+
* the already-allocated instance instead of creating a fresh object. The
|
|
156
|
+
* parent's name selects the default `name` (`TypeError`, ...). */
|
|
157
|
+
xt_value xt_error_init(xt_value thisValue, xt_value nameValue, int32_t argc,
|
|
158
|
+
xt_value *argv) {
|
|
159
|
+
const char *name = XT_IS_STRING(nameValue) ? xt_string_data(nameValue) : "Error";
|
|
160
|
+
if (!xt_error_is_family(name)) name = "Error";
|
|
161
|
+
xt_object_set(thisValue, xt_string_from_cstr("name"), xt_string_from_cstr(name));
|
|
162
|
+
xt_value message;
|
|
163
|
+
if (strcmp(name, "AggregateError") == 0) {
|
|
164
|
+
xt_object_set(thisValue, xt_string_from_cstr("errors"), xt_arg_at(argc, argv, 0));
|
|
165
|
+
message = xt_arg_at(argc, argv, 1);
|
|
166
|
+
} else {
|
|
167
|
+
message = xt_arg_at(argc, argv, 0);
|
|
168
|
+
}
|
|
19
169
|
xt_object_set(thisValue, xt_string_from_cstr("message"),
|
|
20
170
|
message == XT_UNDEFINED ? xt_string_from_cstr("") : message);
|
|
21
171
|
return thisValue;
|
|
@@ -9,9 +9,13 @@ static time_t xt_timegm(struct tm *tm) { return (time_t)_mkgmtime64(tm); }
|
|
|
9
9
|
static struct tm *xt_gmtime_r(const time_t *timer, struct tm *buf) {
|
|
10
10
|
return gmtime_s(buf, timer) == 0 ? buf : NULL;
|
|
11
11
|
}
|
|
12
|
+
static struct tm *xt_localtime_r(const time_t *timer, struct tm *buf) {
|
|
13
|
+
return localtime_s(buf, timer) == 0 ? buf : NULL;
|
|
14
|
+
}
|
|
12
15
|
#else
|
|
13
16
|
static time_t xt_timegm(struct tm *tm) { return timegm(tm); }
|
|
14
17
|
static struct tm *xt_gmtime_r(const time_t *timer, struct tm *buf) { return gmtime_r(timer, buf); }
|
|
18
|
+
static struct tm *xt_localtime_r(const time_t *timer, struct tm *buf) { return localtime_r(timer, buf); }
|
|
15
19
|
#endif
|
|
16
20
|
|
|
17
21
|
int xt_value_equals(xt_value a, xt_value b) {
|
|
@@ -148,24 +148,35 @@ static void xt_json_stringify_array(xt_value value, int indent, int depth, xt_va
|
|
|
148
148
|
static void xt_json_stringify_object(xt_value value, int indent, int depth, xt_value *out) {
|
|
149
149
|
xt_value keys = xt_object_keys(value);
|
|
150
150
|
xt_array *array = xt_as_array(keys);
|
|
151
|
-
if (!array
|
|
151
|
+
if (!array) { *out = xt_add(*out, xt_string_from_cstr("{}")); return; }
|
|
152
|
+
int any = 0;
|
|
153
|
+
for (uint32_t i = 0; i < array->length; i++) {
|
|
154
|
+
xt_value item = xt_object_get(value, array->items[i]);
|
|
155
|
+
if (item != XT_UNDEFINED && !XT_IS_FUNCTION(item) && !xt_is_symbol(item)) { any = 1; break; }
|
|
156
|
+
}
|
|
157
|
+
if (!any) { *out = xt_add(*out, xt_string_from_cstr("{}")); return; }
|
|
152
158
|
*out = xt_add(*out, xt_string_from_cstr("{"));
|
|
159
|
+
int written = 0;
|
|
153
160
|
for (uint32_t i = 0; i < array->length; i++) {
|
|
154
|
-
if (i > 0) *out = xt_add(*out, xt_string_from_cstr(","));
|
|
155
|
-
xt_json_indent(out, indent, depth + 1);
|
|
156
161
|
xt_value key = array->items[i];
|
|
162
|
+
xt_value item = xt_object_get(value, key);
|
|
163
|
+
/* `undefined`, functions and symbols are omitted from objects. */
|
|
164
|
+
if (item == XT_UNDEFINED || XT_IS_FUNCTION(item) || xt_is_symbol(item)) continue;
|
|
165
|
+
if (written > 0) *out = xt_add(*out, xt_string_from_cstr(","));
|
|
166
|
+
written++;
|
|
167
|
+
xt_json_indent(out, indent, depth + 1);
|
|
157
168
|
*out = xt_add(*out, xt_string_from_cstr("\""));
|
|
158
169
|
*out = xt_add(*out, key);
|
|
159
170
|
*out = xt_add(*out, xt_string_from_cstr("\":"));
|
|
160
171
|
if (indent > 0) *out = xt_add(*out, xt_string_from_cstr(" "));
|
|
161
|
-
xt_json_stringify_value(
|
|
172
|
+
xt_json_stringify_value(item, indent, depth + 1, out);
|
|
162
173
|
}
|
|
163
174
|
xt_json_indent(out, indent, depth);
|
|
164
175
|
*out = xt_add(*out, xt_string_from_cstr("}"));
|
|
165
176
|
}
|
|
166
177
|
|
|
167
178
|
static void xt_json_stringify_value(xt_value value, int indent, int depth, xt_value *out) {
|
|
168
|
-
if (value == XT_UNDEFINED || value == XT_NULL || XT_IS_FUNCTION(value)) {
|
|
179
|
+
if (value == XT_UNDEFINED || value == XT_NULL || XT_IS_FUNCTION(value) || xt_is_symbol(value)) {
|
|
169
180
|
*out = xt_add(*out, xt_string_from_cstr("null"));
|
|
170
181
|
return;
|
|
171
182
|
}
|
|
@@ -207,7 +218,9 @@ xt_value xt_json_stringify(int32_t argc, xt_value *argv) {
|
|
|
207
218
|
else if (XT_IS_STRING(space)) indent = (int)((xt_string *)XT_GET_PTR(space))->length;
|
|
208
219
|
if (indent < 0) indent = 0;
|
|
209
220
|
if (indent > 10) indent = 10;
|
|
221
|
+
xt_value value = xt_arg_at(argc, argv, 0);
|
|
222
|
+
if (value == XT_UNDEFINED || XT_IS_FUNCTION(value) || xt_is_symbol(value)) return XT_UNDEFINED;
|
|
210
223
|
xt_value out = xt_string_from_cstr("");
|
|
211
|
-
xt_json_stringify_value(
|
|
224
|
+
xt_json_stringify_value(value, indent, 0, &out);
|
|
212
225
|
return out;
|
|
213
226
|
}
|
|
@@ -60,7 +60,7 @@ xt_value xt_string_static(xt_value name, int32_t argc, xt_value *argv) {
|
|
|
60
60
|
}
|
|
61
61
|
if (strcmp(fn, "raw") == 0) {
|
|
62
62
|
xt_value strings = xt_arg_at(argc, argv, 0);
|
|
63
|
-
xt_value raw =
|
|
63
|
+
xt_value raw = xt_get(strings, xt_string_from_cstr("raw"));
|
|
64
64
|
xt_value out = xt_string_from_cstr("");
|
|
65
65
|
double length = xt_to_number(xt_get(raw, xt_string_from_cstr("length")));
|
|
66
66
|
for (int32_t i = 0; i < (int32_t)length; i++) {
|
|
@@ -8,7 +8,7 @@ xt_value xt_ext_number_method(xt_value target, const char *method, int32_t argc,
|
|
|
8
8
|
if (precision < 0) precision = 0;
|
|
9
9
|
if (precision > 100) precision = 100;
|
|
10
10
|
char buffer[512];
|
|
11
|
-
|
|
11
|
+
xt_number_to_fixed(n, precision, buffer, sizeof(buffer));
|
|
12
12
|
return xt_string_from_cstr(buffer);
|
|
13
13
|
}
|
|
14
14
|
if (strcmp(method, "toPrecision") == 0) {
|
|
@@ -17,15 +17,14 @@ xt_value xt_ext_number_method(xt_value target, const char *method, int32_t argc,
|
|
|
17
17
|
if (precision < 1) precision = 1;
|
|
18
18
|
if (precision > 100) precision = 100;
|
|
19
19
|
char buffer[512];
|
|
20
|
-
|
|
20
|
+
xt_number_to_precision(n, precision, buffer, sizeof(buffer));
|
|
21
21
|
return xt_string_from_cstr(buffer);
|
|
22
22
|
}
|
|
23
23
|
if (strcmp(method, "toExponential") == 0) {
|
|
24
|
-
int precision = argc >= 1 ? xt_to_int32(argv[0]) :
|
|
25
|
-
if (precision < 0) precision = 0;
|
|
24
|
+
int precision = (argc >= 1 && argv[0] != XT_UNDEFINED) ? xt_to_int32(argv[0]) : -1;
|
|
26
25
|
if (precision > 100) precision = 100;
|
|
27
26
|
char buffer[512];
|
|
28
|
-
|
|
27
|
+
xt_number_to_exponential(n, precision, buffer, sizeof(buffer));
|
|
29
28
|
return xt_string_from_cstr(buffer);
|
|
30
29
|
}
|
|
31
30
|
if (strcmp(method, "toString") == 0) {
|
|
@@ -9,10 +9,39 @@ xt_value xt_ext_object_method(xt_value target, const char *method, int32_t argc,
|
|
|
9
9
|
|
|
10
10
|
/* -- Object statics ------------------------------------------------------- */
|
|
11
11
|
|
|
12
|
+
/* `Object.getOwnPropertyNames` differs from `Object.keys` only in that it also
|
|
13
|
+
* reports the non-enumerable `length` of arrays and strings. */
|
|
14
|
+
static xt_value xt_object_own_property_names(xt_value value) {
|
|
15
|
+
xt_value names = xt_object_keys(value);
|
|
16
|
+
if (XT_IS_ARRAY(value) || XT_IS_STRING(value)) xt_array_push(names, xt_string_from_cstr("length"));
|
|
17
|
+
return names;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* `Object.groupBy(items, fn)`: bucket each element by the key `fn` returns. */
|
|
21
|
+
static xt_value xt_object_group_by(xt_value value, xt_value fn) {
|
|
22
|
+
xt_value result = xt_object_new();
|
|
23
|
+
xt_array *array = xt_as_array(value);
|
|
24
|
+
if (!array) return result;
|
|
25
|
+
for (uint32_t i = 0; i < array->length; i++) {
|
|
26
|
+
xt_value args[2] = {array->items[i], xt_number((double)i)};
|
|
27
|
+
xt_value keyString = xt_to_string(xt_closure_call(fn, 2, args));
|
|
28
|
+
xt_value group = xt_object_get(result, keyString);
|
|
29
|
+
if (!XT_IS_ARRAY(group)) {
|
|
30
|
+
group = xt_array_new(0, NULL);
|
|
31
|
+
xt_object_set(result, keyString, group);
|
|
32
|
+
}
|
|
33
|
+
xt_array_push(group, array->items[i]);
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
|
|
12
38
|
xt_value xt_object_static(xt_value name, int32_t argc, xt_value *argv) {
|
|
13
39
|
const char *fn = xt_string_data(name);
|
|
14
40
|
if (!fn) return XT_UNDEFINED;
|
|
15
41
|
if (strcmp(fn, "keys") == 0) return xt_object_keys(xt_arg_at(argc, argv, 0));
|
|
42
|
+
if (strcmp(fn, "getOwnPropertyNames") == 0) return xt_object_own_property_names(xt_arg_at(argc, argv, 0));
|
|
43
|
+
if (strcmp(fn, "getOwnPropertySymbols") == 0) return xt_object_own_property_symbols(xt_arg_at(argc, argv, 0));
|
|
44
|
+
if (strcmp(fn, "groupBy") == 0) return xt_object_group_by(xt_arg_at(argc, argv, 0), xt_arg_at(argc, argv, 1));
|
|
16
45
|
if (strcmp(fn, "values") == 0) return xt_object_values(xt_arg_at(argc, argv, 0));
|
|
17
46
|
if (strcmp(fn, "entries") == 0) return xt_object_entries(xt_arg_at(argc, argv, 0));
|
|
18
47
|
if (strcmp(fn, "assign") == 0) return xt_object_assign(argc, argv);
|