xbintsc 0.3.87 → 0.5.20
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/AGENTS.md +23 -11
- package/README.md +11 -9
- package/README.zh-CN.md +7 -7
- package/dist/src/binder/declarations.js +14 -3
- package/dist/src/binder/declarations.js.map +1 -1
- package/dist/src/cli/hints.js +7 -1
- package/dist/src/cli/hints.js.map +1 -1
- package/dist/src/cli/main.js +115 -15
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/cli/watch.d.ts +25 -0
- package/dist/src/cli/watch.js +93 -0
- package/dist/src/cli/watch.js.map +1 -0
- package/dist/src/codegen/generator/calls/access.js +17 -4
- package/dist/src/codegen/generator/calls/access.js.map +1 -1
- package/dist/src/codegen/generator/calls/closures.js +13 -1
- package/dist/src/codegen/generator/calls/closures.js.map +1 -1
- package/dist/src/codegen/generator/calls/invocation.js +4 -3
- package/dist/src/codegen/generator/calls/invocation.js.map +1 -1
- package/dist/src/codegen/generator/context.d.ts +8 -0
- package/dist/src/codegen/generator/context.js +22 -3
- package/dist/src/codegen/generator/context.js.map +1 -1
- package/dist/src/codegen/generator/expressions/operators.js +17 -15
- package/dist/src/codegen/generator/expressions/operators.js.map +1 -1
- package/dist/src/codegen/generator/expressions/primary.js +11 -1
- package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
- package/dist/src/codegen/generator/module.d.ts +0 -1
- package/dist/src/codegen/generator/module.js +10 -17
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/numeric.d.ts +6 -3
- package/dist/src/codegen/generator/numeric.js +54 -11
- package/dist/src/codegen/generator/numeric.js.map +1 -1
- package/dist/src/codegen/generator/state.js +27 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/statements/control-flow.js +2 -7
- package/dist/src/codegen/generator/statements/control-flow.js.map +1 -1
- package/dist/src/codegen/generator/statements/loops.js +48 -16
- package/dist/src/codegen/generator/statements/loops.js.map +1 -1
- package/dist/src/codegen/generator/tables.d.ts +9 -0
- package/dist/src/codegen/generator/tables.js +100 -3
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/diagnostics/diagnostic.d.ts +3 -1
- package/dist/src/diagnostics/diagnostic.js +23 -3
- package/dist/src/diagnostics/diagnostic.js.map +1 -1
- package/dist/src/driver/app-artifacts.d.ts +42 -0
- package/dist/src/driver/app-artifacts.js +53 -0
- package/dist/src/driver/app-artifacts.js.map +1 -0
- package/dist/src/driver/build-key.d.ts +29 -0
- package/dist/src/driver/build-key.js +35 -0
- package/dist/src/driver/build-key.js.map +1 -0
- package/dist/src/driver/bundler/graph.js +61 -12
- package/dist/src/driver/bundler/graph.js.map +1 -1
- package/dist/src/driver/bundler/merge.js +7 -1
- package/dist/src/driver/bundler/merge.js.map +1 -1
- package/dist/src/driver/compiler.d.ts +10 -67
- package/dist/src/driver/compiler.js +94 -230
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/config.d.ts +3 -0
- package/dist/src/driver/config.js +8 -0
- package/dist/src/driver/config.js.map +1 -1
- package/dist/src/driver/frontend.d.ts +37 -0
- package/dist/src/driver/frontend.js +92 -0
- package/dist/src/driver/frontend.js.map +1 -0
- package/dist/src/driver/index.d.ts +1 -1
- package/dist/src/driver/index.js.map +1 -1
- package/dist/src/driver/options.d.ts +64 -0
- package/dist/src/driver/options.js +9 -0
- package/dist/src/driver/options.js.map +1 -0
- package/dist/src/driver/runtime-objects.d.ts +38 -0
- package/dist/src/driver/runtime-objects.js +111 -0
- package/dist/src/driver/runtime-objects.js.map +1 -0
- package/dist/src/driver/toolchain-provider.d.ts +4 -0
- package/dist/src/driver/toolchain-provider.js +4 -0
- package/dist/src/driver/toolchain-provider.js.map +1 -1
- package/dist/src/driver/toolchain.d.ts +32 -1
- package/dist/src/driver/toolchain.js +115 -11
- package/dist/src/driver/toolchain.js.map +1 -1
- package/dist/src/driver/version.d.ts +12 -0
- package/dist/src/driver/version.js +13 -0
- package/dist/src/driver/version.js.map +1 -0
- package/dist/src/driver/win-icon.d.ts +7 -9
- package/dist/src/driver/win-icon.js +37 -35
- package/dist/src/driver/win-icon.js.map +1 -1
- package/dist/src/parser/declarations/classes.js +5 -0
- package/dist/src/parser/declarations/classes.js.map +1 -1
- package/dist/src/parser/declarations/functions.js +13 -1
- package/dist/src/parser/declarations/functions.js.map +1 -1
- package/dist/src/parser/modules.js +8 -3
- package/dist/src/parser/modules.js.map +1 -1
- package/dist/src/parser/parser.d.ts +1 -0
- package/dist/src/parser/parser.js +23 -0
- package/dist/src/parser/parser.js.map +1 -1
- package/dist/tests/cli/check.test.d.ts +6 -0
- package/dist/tests/cli/check.test.js +68 -0
- package/dist/tests/cli/check.test.js.map +1 -0
- package/dist/tests/cli/main.test.js +19 -0
- package/dist/tests/cli/main.test.js.map +1 -1
- package/dist/tests/cli/watch.test.d.ts +6 -0
- package/dist/tests/cli/watch.test.js +72 -0
- package/dist/tests/cli/watch.test.js.map +1 -0
- package/dist/tests/codegen/closures.test.js +8 -0
- package/dist/tests/codegen/closures.test.js.map +1 -1
- package/dist/tests/codegen/expressions.test.js +15 -3
- package/dist/tests/codegen/expressions.test.js.map +1 -1
- package/dist/tests/codegen/llvm.test.js +16 -0
- package/dist/tests/codegen/llvm.test.js.map +1 -1
- package/dist/tests/diagnostics/diagnostic.test.js +8 -0
- package/dist/tests/diagnostics/diagnostic.test.js.map +1 -1
- package/dist/tests/docs/structure.test.d.ts +1 -0
- package/dist/tests/docs/structure.test.js +92 -0
- package/dist/tests/docs/structure.test.js.map +1 -0
- package/dist/tests/driver/compiler.test.js +6 -0
- package/dist/tests/driver/compiler.test.js.map +1 -1
- package/dist/tests/driver/config.test.js +9 -0
- package/dist/tests/driver/config.test.js.map +1 -1
- package/dist/tests/driver/icon.test.js +19 -32
- package/dist/tests/driver/icon.test.js.map +1 -1
- package/dist/tests/driver/invalid-input.test.d.ts +10 -0
- package/dist/tests/driver/invalid-input.test.js +29 -0
- package/dist/tests/driver/invalid-input.test.js.map +1 -0
- package/dist/tests/driver/modules.test.js +42 -3
- package/dist/tests/driver/modules.test.js.map +1 -1
- package/dist/tests/driver/toolchain-provider.test.js +27 -1
- package/dist/tests/driver/toolchain-provider.test.js.map +1 -1
- package/dist/tests/driver/toolchain.test.js +60 -2
- package/dist/tests/driver/toolchain.test.js.map +1 -1
- package/dist/tests/e2e/array-buffer.test.d.ts +5 -0
- package/dist/tests/e2e/array-buffer.test.js +38 -0
- package/dist/tests/e2e/array-buffer.test.js.map +1 -0
- package/dist/tests/e2e/array-from-iterables.test.d.ts +7 -0
- package/dist/tests/e2e/array-from-iterables.test.js +34 -0
- package/dist/tests/e2e/array-from-iterables.test.js.map +1 -0
- package/dist/tests/e2e/array-symbol-iterator.test.d.ts +8 -0
- package/dist/tests/e2e/array-symbol-iterator.test.js +42 -0
- package/dist/tests/e2e/array-symbol-iterator.test.js.map +1 -0
- package/dist/tests/e2e/async-await.test.d.ts +10 -0
- package/dist/tests/e2e/async-await.test.js +247 -0
- package/dist/tests/e2e/async-await.test.js.map +1 -0
- package/dist/tests/e2e/async-generators.test.d.ts +1 -0
- package/dist/tests/e2e/async-generators.test.js +154 -0
- package/dist/tests/e2e/async-generators.test.js.map +1 -0
- package/dist/tests/e2e/await-ordering.test.d.ts +5 -0
- package/dist/tests/e2e/await-ordering.test.js +37 -0
- package/dist/tests/e2e/await-ordering.test.js.map +1 -0
- package/dist/tests/e2e/compile-builtins.test.js +1 -1
- package/dist/tests/e2e/compile-modules.test.js +7 -0
- package/dist/tests/e2e/compile-modules.test.js.map +1 -1
- package/dist/tests/e2e/date-parse.test.d.ts +8 -0
- package/dist/tests/e2e/date-parse.test.js +38 -0
- package/dist/tests/e2e/date-parse.test.js.map +1 -0
- package/dist/tests/e2e/default-anonymous-exports.test.d.ts +7 -0
- package/dist/tests/e2e/default-anonymous-exports.test.js +23 -0
- package/dist/tests/e2e/default-anonymous-exports.test.js.map +1 -0
- package/dist/tests/e2e/globals-microtask.test.d.ts +9 -0
- package/dist/tests/e2e/globals-microtask.test.js +37 -0
- package/dist/tests/e2e/globals-microtask.test.js.map +1 -0
- package/dist/tests/e2e/gui-media.test.js +8 -1
- package/dist/tests/e2e/gui-media.test.js.map +1 -1
- package/dist/tests/e2e/inspect-builtins.test.d.ts +10 -0
- package/dist/tests/e2e/inspect-builtins.test.js +43 -0
- package/dist/tests/e2e/inspect-builtins.test.js.map +1 -0
- package/dist/tests/e2e/json-builtin-objects.test.d.ts +9 -0
- package/dist/tests/e2e/json-builtin-objects.test.js +23 -0
- package/dist/tests/e2e/json-builtin-objects.test.js.map +1 -0
- package/dist/tests/e2e/json-circular.test.d.ts +6 -0
- package/dist/tests/e2e/json-circular.test.js +43 -0
- package/dist/tests/e2e/json-circular.test.js.map +1 -0
- package/dist/tests/e2e/json-parse-reviver.test.d.ts +6 -0
- package/dist/tests/e2e/json-parse-reviver.test.js +29 -0
- package/dist/tests/e2e/json-parse-reviver.test.js.map +1 -0
- package/dist/tests/e2e/json-stringify-replacer.test.d.ts +6 -0
- package/dist/tests/e2e/json-stringify-replacer.test.js +27 -0
- package/dist/tests/e2e/json-stringify-replacer.test.js.map +1 -0
- package/dist/tests/e2e/json-stringify-space.test.d.ts +6 -0
- package/dist/tests/e2e/json-stringify-space.test.js +23 -0
- package/dist/tests/e2e/json-stringify-space.test.js.map +1 -0
- package/dist/tests/e2e/method-dispatch-errors.test.d.ts +9 -0
- package/dist/tests/e2e/method-dispatch-errors.test.js +38 -0
- package/dist/tests/e2e/method-dispatch-errors.test.js.map +1 -0
- package/dist/tests/e2e/native-extensions.test.js +1 -1
- package/dist/tests/e2e/native-extensions.test.js.map +1 -1
- package/dist/tests/e2e/promise-with-resolvers.test.d.ts +5 -0
- package/dist/tests/e2e/promise-with-resolvers.test.js +20 -0
- package/dist/tests/e2e/promise-with-resolvers.test.js.map +1 -0
- package/dist/tests/e2e/property-descriptors.test.d.ts +5 -0
- package/dist/tests/e2e/property-descriptors.test.js +25 -0
- package/dist/tests/e2e/property-descriptors.test.js.map +1 -0
- package/dist/tests/e2e/property-ic.test.d.ts +1 -0
- package/dist/tests/e2e/property-ic.test.js +55 -0
- package/dist/tests/e2e/property-ic.test.js.map +1 -0
- package/dist/tests/e2e/runtime-coverage-globals.test.js +46 -0
- package/dist/tests/e2e/runtime-coverage-globals.test.js.map +1 -1
- package/dist/tests/e2e/runtime-errors.test.d.ts +10 -0
- package/dist/tests/e2e/runtime-errors.test.js +52 -0
- package/dist/tests/e2e/runtime-errors.test.js.map +1 -0
- package/dist/tests/e2e/string-utf16.test.d.ts +6 -0
- package/dist/tests/e2e/string-utf16.test.js +133 -0
- package/dist/tests/e2e/string-utf16.test.js.map +1 -0
- package/dist/tests/e2e/structured-clone.test.d.ts +6 -0
- package/dist/tests/e2e/structured-clone.test.js +49 -0
- package/dist/tests/e2e/structured-clone.test.js.map +1 -0
- package/dist/tests/e2e/text-codec.test.d.ts +6 -0
- package/dist/tests/e2e/text-codec.test.js +24 -0
- package/dist/tests/e2e/text-codec.test.js.map +1 -0
- package/dist/tests/e2e/typed-array-views.test.d.ts +6 -0
- package/dist/tests/e2e/typed-array-views.test.js +39 -0
- package/dist/tests/e2e/typed-array-views.test.js.map +1 -0
- package/dist/tests/e2e/url-search-params.test.d.ts +5 -0
- package/dist/tests/e2e/url-search-params.test.js +30 -0
- package/dist/tests/e2e/url-search-params.test.js.map +1 -0
- package/dist/tests/e2e/weak-collections.test.d.ts +1 -0
- package/dist/tests/e2e/weak-collections.test.js +88 -0
- package/dist/tests/e2e/weak-collections.test.js.map +1 -0
- package/dist/tests/parser/declarations.test.js +12 -0
- package/dist/tests/parser/declarations.test.js.map +1 -1
- package/dist/tests/parser/module-syntax.test.js +9 -0
- package/dist/tests/parser/module-syntax.test.js.map +1 -1
- package/dist/tests/parser/parser.test.js +7 -0
- package/dist/tests/parser/parser.test.js.map +1 -1
- package/dist/tests/version.test.js +5 -1
- package/dist/tests/version.test.js.map +1 -1
- package/doc/ai/README.md +4 -3
- package/doc/ai/cli.md +41 -0
- package/doc/ai/contributing.md +26 -21
- package/doc/ai/extensions.md +12 -9
- package/doc/ai/language-support.md +26 -19
- package/doc/ai/troubleshooting.md +15 -12
- package/doc/ai/zh-CN/README.md +3 -2
- package/doc/ai/zh-CN/cli.md +35 -0
- package/doc/ai/zh-CN/contributing.md +19 -18
- package/doc/ai/zh-CN/extensions.md +10 -7
- package/doc/ai/zh-CN/language-support.md +26 -20
- package/doc/ai/zh-CN/troubleshooting.md +12 -10
- package/doc/gui/build.md +13 -4
- package/doc/gui/known-issues.md +9 -5
- package/doc/gui/rendering.md +3 -1
- package/doc/gui.md +4 -3
- package/doc/icon.md +5 -4
- package/doc/implemented/async.md +38 -0
- package/doc/implemented/binder.md +13 -0
- package/doc/implemented/cli.md +47 -0
- package/doc/implemented/codegen.md +33 -0
- package/doc/implemented/collections.md +26 -0
- package/doc/implemented/driver.md +19 -0
- package/doc/implemented/extensions.md +19 -0
- package/doc/implemented/fetch.md +12 -0
- package/doc/implemented/lexer.md +23 -0
- package/doc/implemented/modules.md +28 -0
- package/doc/implemented/node/assert.md +17 -0
- package/doc/implemented/node/buffer.md +29 -0
- package/doc/implemented/node/child-process.md +29 -0
- package/doc/implemented/node/crypto.md +9 -0
- package/doc/implemented/node/dgram.md +15 -0
- package/doc/implemented/node/events.md +37 -0
- package/doc/implemented/node/fs-promises.md +38 -0
- package/doc/implemented/node/fs.md +112 -0
- package/doc/implemented/node/http.md +21 -0
- package/doc/implemented/node/net.md +17 -0
- package/doc/implemented/node/os.md +22 -0
- package/doc/implemented/node/path.md +33 -0
- package/doc/implemented/node/process.md +23 -0
- package/doc/implemented/node/querystring.md +20 -0
- package/doc/implemented/node/stream-promises.md +8 -0
- package/doc/implemented/node/stream.md +19 -0
- package/doc/implemented/node/test.md +10 -0
- package/doc/implemented/node/url.md +8 -0
- package/doc/implemented/node/util.md +25 -0
- package/doc/implemented/node/worker-threads.md +10 -0
- package/doc/implemented/node/zlib.md +8 -0
- package/doc/implemented/node.md +48 -0
- package/doc/implemented/operators.md +38 -0
- package/doc/implemented/parser.md +58 -0
- package/doc/implemented/pipeline.md +28 -0
- package/doc/implemented/runtime-core.md +32 -0
- package/doc/implemented/stdlib.md +78 -0
- package/doc/implemented/strings.md +27 -0
- package/doc/implemented/tests.md +10 -0
- package/doc/implemented/typed-arrays.md +26 -0
- package/doc/implemented/value-model.md +18 -0
- package/doc/implemented.md +54 -352
- package/doc/node-implemented.md +3 -585
- package/doc/node-unimplemented.md +3 -164
- package/doc/requirements.md +23 -8
- package/doc/unimplemented/classes.md +22 -0
- package/doc/unimplemented/deviations.md +27 -0
- package/doc/unimplemented/expressions.md +26 -0
- package/doc/unimplemented/functions.md +21 -0
- package/doc/unimplemented/modules.md +22 -0
- package/doc/unimplemented/node/async.md +17 -0
- package/doc/unimplemented/node/bun.md +9 -0
- package/doc/unimplemented/node/fs-promises.md +16 -0
- package/doc/unimplemented/node/fs.md +31 -0
- package/doc/unimplemented/node/globals.md +23 -0
- package/doc/unimplemented/node/modules.md +21 -0
- package/doc/unimplemented/node.md +21 -0
- package/doc/unimplemented/statements.md +18 -0
- package/doc/unimplemented/stdlib.md +54 -0
- package/doc/unimplemented/toolchain.md +14 -0
- package/doc/unimplemented/types.md +12 -0
- package/doc/unimplemented.md +18 -274
- package/doc/xbintsc.config.schema.json +12 -0
- package/doc/zh-CN/gui/build.md +11 -3
- package/doc/zh-CN/gui/known-issues.md +9 -4
- package/doc/zh-CN/gui/rendering.md +2 -1
- package/doc/zh-CN/gui.md +3 -2
- package/doc/zh-CN/icon.md +5 -4
- package/doc/zh-CN/implemented/async.md +38 -0
- package/doc/zh-CN/implemented/binder.md +13 -0
- package/doc/zh-CN/implemented/cli.md +46 -0
- package/doc/zh-CN/implemented/codegen.md +33 -0
- package/doc/zh-CN/implemented/collections.md +26 -0
- package/doc/zh-CN/implemented/driver.md +19 -0
- package/doc/zh-CN/implemented/extensions.md +19 -0
- package/doc/zh-CN/implemented/fetch.md +12 -0
- package/doc/zh-CN/implemented/lexer.md +23 -0
- package/doc/zh-CN/implemented/modules.md +28 -0
- package/doc/zh-CN/implemented/node/assert.md +17 -0
- package/doc/zh-CN/implemented/node/buffer.md +25 -0
- package/doc/zh-CN/implemented/node/child-process.md +27 -0
- package/doc/zh-CN/implemented/node/crypto.md +9 -0
- package/doc/zh-CN/implemented/node/dgram.md +15 -0
- package/doc/zh-CN/implemented/node/events.md +36 -0
- package/doc/zh-CN/implemented/node/fs-promises.md +27 -0
- package/doc/zh-CN/implemented/node/fs.md +105 -0
- package/doc/zh-CN/implemented/node/http.md +17 -0
- package/doc/zh-CN/implemented/node/net.md +17 -0
- package/doc/zh-CN/implemented/node/os.md +21 -0
- package/doc/zh-CN/implemented/node/path.md +26 -0
- package/doc/zh-CN/implemented/node/process.md +23 -0
- package/doc/zh-CN/implemented/node/querystring.md +20 -0
- package/doc/zh-CN/implemented/node/stream-promises.md +8 -0
- package/doc/zh-CN/implemented/node/stream.md +15 -0
- package/doc/zh-CN/implemented/node/test.md +10 -0
- package/doc/zh-CN/implemented/node/url.md +8 -0
- package/doc/zh-CN/implemented/node/util.md +25 -0
- package/doc/zh-CN/implemented/node/worker-threads.md +9 -0
- package/doc/zh-CN/implemented/node/zlib.md +8 -0
- package/doc/zh-CN/implemented/node.md +45 -0
- package/doc/zh-CN/implemented/operators.md +38 -0
- package/doc/zh-CN/implemented/parser.md +58 -0
- package/doc/zh-CN/implemented/pipeline.md +25 -0
- package/doc/zh-CN/implemented/runtime-core.md +31 -0
- package/doc/zh-CN/implemented/stdlib.md +76 -0
- package/doc/zh-CN/implemented/strings.md +27 -0
- package/doc/zh-CN/implemented/tests.md +10 -0
- package/doc/zh-CN/implemented/typed-arrays.md +26 -0
- package/doc/zh-CN/implemented/value-model.md +18 -0
- package/doc/zh-CN/implemented.md +50 -347
- package/doc/zh-CN/node-implemented.md +4 -531
- package/doc/zh-CN/node-unimplemented.md +4 -139
- package/doc/zh-CN/plan-require-node-modules.md +4 -4
- package/doc/zh-CN/requirements.md +20 -6
- package/doc/zh-CN/unimplemented/classes.md +22 -0
- package/doc/zh-CN/unimplemented/deviations.md +24 -0
- package/doc/zh-CN/unimplemented/expressions.md +24 -0
- package/doc/zh-CN/unimplemented/functions.md +21 -0
- package/doc/zh-CN/unimplemented/modules.md +19 -0
- package/doc/zh-CN/unimplemented/node/async.md +17 -0
- package/doc/zh-CN/unimplemented/node/bun.md +8 -0
- package/doc/zh-CN/unimplemented/node/fs-promises.md +12 -0
- package/doc/zh-CN/unimplemented/node/fs.md +24 -0
- package/doc/zh-CN/unimplemented/node/globals.md +14 -0
- package/doc/zh-CN/unimplemented/node/modules.md +15 -0
- package/doc/zh-CN/unimplemented/node.md +18 -0
- package/doc/zh-CN/unimplemented/statements.md +15 -0
- package/doc/zh-CN/unimplemented/stdlib.md +54 -0
- package/doc/zh-CN/unimplemented/toolchain.md +14 -0
- package/doc/zh-CN/unimplemented/types.md +11 -0
- package/doc/zh-CN/unimplemented.md +14 -236
- package/llms.txt +32 -4
- package/package.json +1 -1
- package/runtime/ext_gui/renderer_shaders.h +2 -2
- package/runtime/ext_gui/stb_image.h +1 -17
- package/runtime/ext_node/child_process/child_process.c +173 -73
- package/runtime/rt.h +47 -0
- package/runtime/rt_internal.h +205 -10
- package/runtime/xt_alloc.c +49 -7
- package/runtime/xt_array_buffer.c +284 -0
- package/runtime/xt_async.c +222 -0
- package/runtime/xt_bigint/helpers.inc +3 -3
- package/runtime/xt_builtins.c +59 -51
- package/runtime/xt_constructors.c +399 -0
- package/runtime/xt_containers/access.inc +195 -14
- package/runtime/xt_containers/arrays.inc +26 -2
- package/runtime/xt_containers/objects.inc +226 -5
- package/runtime/xt_containers/shapes.inc +71 -0
- package/runtime/xt_containers.c +1 -0
- package/runtime/xt_coroutine.c +229 -0
- package/runtime/xt_generator.c +325 -167
- package/runtime/xt_io/inspect.inc +147 -2
- package/runtime/xt_loop.c +35 -4
- package/runtime/xt_performance.c +37 -0
- package/runtime/xt_promise.c +125 -18
- package/runtime/xt_stdlib/arrays.inc +1 -1
- package/runtime/xt_stdlib/dispatch.inc +64 -13
- package/runtime/xt_stdlib/strings.inc +74 -17
- package/runtime/xt_stdlib2/array-statics.inc +28 -3
- package/runtime/xt_stdlib2/arrays.inc +5 -3
- package/runtime/xt_stdlib2/container.inc +5 -0
- package/runtime/xt_stdlib2/date.inc +111 -3
- package/runtime/xt_stdlib2/error.inc +35 -0
- package/runtime/xt_stdlib2/json.inc +353 -33
- package/runtime/xt_stdlib2/number-string-statics.inc +24 -15
- package/runtime/xt_stdlib2/objects.inc +123 -1
- package/runtime/xt_stdlib2/regexp-match.inc +2 -2
- package/runtime/xt_stdlib2/set.inc +7 -1
- package/runtime/xt_stdlib2/strings.inc +70 -40
- package/runtime/xt_structured_clone.c +159 -0
- package/runtime/xt_symbol.c +2 -2
- package/runtime/xt_text_codec.c +69 -0
- package/runtime/xt_typed_array/construction.inc +78 -7
- package/runtime/xt_typed_array/elements.inc +159 -0
- package/runtime/xt_typed_array/methods.inc +21 -5
- package/runtime/xt_typed_array.c +11 -10
- package/runtime/xt_url.c +375 -0
- package/runtime/xt_values/arithmetic.inc +2 -2
- package/runtime/xt_values/constructors.inc +8 -0
- package/runtime/xt_values/conversions.inc +1 -1
- package/runtime/xt_values/strings.inc +19 -3
- package/runtime/xt_values/utf16.inc +340 -0
- package/runtime/xt_values.c +1 -0
- package/runtime/xt_weak.c +281 -0
- package/scripts/build-gui.ts +133 -60
- package/scripts/check-version.ts +3 -3
- package/src/binder/declarations.ts +14 -3
- package/src/cli/hints.ts +8 -1
- package/src/cli/main.ts +119 -18
- package/src/cli/watch.ts +101 -0
- package/src/codegen/generator/calls/access.ts +17 -4
- package/src/codegen/generator/calls/closures.ts +12 -1
- package/src/codegen/generator/calls/invocation.ts +4 -3
- package/src/codegen/generator/context.ts +23 -3
- package/src/codegen/generator/expressions/operators.ts +27 -13
- package/src/codegen/generator/expressions/primary.ts +10 -1
- package/src/codegen/generator/module.ts +10 -19
- package/src/codegen/generator/numeric.ts +85 -11
- package/src/codegen/generator/state.ts +27 -0
- package/src/codegen/generator/statements/control-flow.ts +2 -6
- package/src/codegen/generator/statements/loops.ts +50 -16
- package/src/codegen/generator/tables.ts +110 -3
- package/src/diagnostics/diagnostic.ts +23 -3
- package/src/driver/app-artifacts.ts +77 -0
- package/src/driver/build-key.ts +55 -0
- package/src/driver/bundler/graph.ts +63 -13
- package/src/driver/bundler/merge.ts +4 -1
- package/src/driver/compiler.ts +93 -324
- package/src/driver/config.ts +11 -0
- package/src/driver/frontend.ts +120 -0
- package/src/driver/index.ts +0 -1
- package/src/driver/options.ts +70 -0
- package/src/driver/runtime-objects.ts +133 -0
- package/src/driver/toolchain-provider.ts +4 -0
- package/src/driver/toolchain.ts +154 -10
- package/src/driver/version.ts +12 -0
- package/src/driver/win-icon.ts +36 -36
- package/src/parser/declarations/classes.ts +4 -0
- package/src/parser/declarations/functions.ts +12 -1
- package/src/parser/modules.ts +8 -4
- package/src/parser/parser.ts +28 -0
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
/* Generic member access */
|
|
3
3
|
/* ------------------------------------------------------------------------- */
|
|
4
4
|
|
|
5
|
+
/* Inherited lookup for values whose representation is not an `xt_object`
|
|
6
|
+
* property table (Map/Set/Date/RegExp/Promise/Symbol). `__proto__` returns the
|
|
7
|
+
* prototype itself instead of invoking Object.prototype's getter with the
|
|
8
|
+
* wrong receiver. */
|
|
9
|
+
static xt_value xt_get_inherited(xt_value target, xt_value key) {
|
|
10
|
+
xt_value proto = xt_object_get_prototype(target);
|
|
11
|
+
if (proto == XT_UNDEFINED || proto == XT_NULL || proto == target) return XT_UNDEFINED;
|
|
12
|
+
if (XT_IS_STRING(key)) {
|
|
13
|
+
xt_string *k = xt_as_string(key);
|
|
14
|
+
if (k->length == 9 && memcmp(xt_string_bytes(k), "__proto__", 9) == 0) return proto;
|
|
15
|
+
}
|
|
16
|
+
return xt_get(proto, key);
|
|
17
|
+
}
|
|
18
|
+
|
|
5
19
|
/*
|
|
6
20
|
* Reading a property of `null` / `undefined` is a TypeError in JavaScript.
|
|
7
21
|
* Short-circuiting `?.` guards forbid reaching this point for a nullish
|
|
@@ -18,7 +32,77 @@ static void xt_throw_read_of_nullish(xt_value target, xt_value key) {
|
|
|
18
32
|
char message[256];
|
|
19
33
|
snprintf(message, sizeof(message),
|
|
20
34
|
"TypeError: Cannot read properties of %s (reading '%s')", base, keybuf);
|
|
21
|
-
xt_throw(
|
|
35
|
+
xt_throw(xt_error_from_message(message));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* -- Array.prototype[Symbol.iterator] -------------------------------------- */
|
|
39
|
+
/*
|
|
40
|
+
* `for...of` and spread use the internal index protocol, but libraries also
|
|
41
|
+
* call the iterator method explicitly (`arr[Symbol.iterator]()`, `Array.from`,
|
|
42
|
+
* manual `.next()`). Build a small iterator object per call: `next` closes over
|
|
43
|
+
* the array and a one-element box holding the current index, and the iterator
|
|
44
|
+
* is itself iterable so it can be passed back to `for...of` / spread.
|
|
45
|
+
*/
|
|
46
|
+
static xt_value xt_array_iterator_next(xt_value thisValue, xt_value env, int32_t argc,
|
|
47
|
+
xt_value *argv) {
|
|
48
|
+
(void)thisValue;
|
|
49
|
+
(void)argc;
|
|
50
|
+
(void)argv;
|
|
51
|
+
xt_value array = xt_closure_env(env, 0);
|
|
52
|
+
xt_value indexBox = xt_closure_env(env, 1);
|
|
53
|
+
int32_t index = xt_to_int32(xt_get(indexBox, xt_number(0)));
|
|
54
|
+
xt_array *items = xt_as_array(array);
|
|
55
|
+
xt_value result = xt_object_new();
|
|
56
|
+
if (!items || index < 0 || (uint32_t)index >= items->length) {
|
|
57
|
+
xt_object_set(result, xt_string_from_cstr("value"), XT_UNDEFINED);
|
|
58
|
+
xt_object_set(result, xt_string_from_cstr("done"), XT_TRUE);
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
xt_object_set(result, xt_string_from_cstr("value"), items->items[index]);
|
|
62
|
+
xt_object_set(result, xt_string_from_cstr("done"), XT_FALSE);
|
|
63
|
+
xt_set(indexBox, xt_number(0), xt_number(index + 1));
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static xt_value xt_iterator_return_this(xt_value thisValue, xt_value env, int32_t argc,
|
|
68
|
+
xt_value *argv) {
|
|
69
|
+
(void)env;
|
|
70
|
+
(void)argc;
|
|
71
|
+
(void)argv;
|
|
72
|
+
return thisValue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static xt_value xt_array_iterator(xt_value thisValue, xt_value env, int32_t argc,
|
|
76
|
+
xt_value *argv) {
|
|
77
|
+
(void)env;
|
|
78
|
+
(void)argc;
|
|
79
|
+
(void)argv;
|
|
80
|
+
if (!XT_IS_ARRAY(thisValue)) {
|
|
81
|
+
xt_value message =
|
|
82
|
+
xt_string_from_cstr("Array.prototype[Symbol.iterator] called on a non-array");
|
|
83
|
+
xt_throw(xt_type_error_ctor(1, &message));
|
|
84
|
+
}
|
|
85
|
+
xt_value indexBox = xt_array_new(0, NULL);
|
|
86
|
+
xt_array_push(indexBox, xt_number(0));
|
|
87
|
+
xt_value captured[2] = {thisValue, indexBox};
|
|
88
|
+
xt_value iterator = xt_object_new();
|
|
89
|
+
xt_object_set(iterator, xt_string_from_cstr("next"),
|
|
90
|
+
xt_closure_new((void *)xt_array_iterator_next, 2, captured));
|
|
91
|
+
xt_object_set(iterator, xt_symbol_well_known("iterator"),
|
|
92
|
+
xt_closure_new((void *)xt_iterator_return_this, 0, NULL));
|
|
93
|
+
return iterator;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* The method value is stable (`arr[Symbol.iterator] === arr[Symbol.iterator]`),
|
|
97
|
+
* so cache it and root the cache for the collector. */
|
|
98
|
+
static xt_value xt_array_iterator_method_value = XT_UNDEFINED;
|
|
99
|
+
|
|
100
|
+
static xt_value xt_array_iterator_method(void) {
|
|
101
|
+
if (!XT_IS_FUNCTION(xt_array_iterator_method_value)) {
|
|
102
|
+
xt_array_iterator_method_value = xt_closure_new((void *)xt_array_iterator, 0, NULL);
|
|
103
|
+
xt_gc_add_root(&xt_array_iterator_method_value);
|
|
104
|
+
}
|
|
105
|
+
return xt_array_iterator_method_value;
|
|
22
106
|
}
|
|
23
107
|
|
|
24
108
|
xt_value xt_get(xt_value target, xt_value key) {
|
|
@@ -37,8 +121,16 @@ xt_value xt_get(xt_value target, xt_value key) {
|
|
|
37
121
|
xt_value value = xt_object_get(extra, key);
|
|
38
122
|
if (value != XT_UNDEFINED) return value;
|
|
39
123
|
}
|
|
40
|
-
/* Fall back to first-class built-in methods (`arr.map`)
|
|
41
|
-
|
|
124
|
+
/* Fall back to first-class built-in methods (`arr.map`) and then to
|
|
125
|
+
* the array's [[Prototype]] (`arr.hasOwnProperty`). */
|
|
126
|
+
xt_value method = xt_method_value(target, key);
|
|
127
|
+
if (method != XT_UNDEFINED) return method;
|
|
128
|
+
xt_value proto = ((xt_array *)XT_GET_PTR(target))->prototype;
|
|
129
|
+
if (proto != XT_UNDEFINED && proto != XT_NULL) {
|
|
130
|
+
if (k->length == 9 && memcmp(xt_string_bytes(k), "__proto__", 9) == 0) return proto;
|
|
131
|
+
return xt_get(proto, key);
|
|
132
|
+
}
|
|
133
|
+
return XT_UNDEFINED;
|
|
42
134
|
}
|
|
43
135
|
return xt_array_get(target, key);
|
|
44
136
|
}
|
|
@@ -49,7 +141,14 @@ xt_value xt_get(xt_value target, xt_value key) {
|
|
|
49
141
|
xt_value value = xt_object_get(extra, key);
|
|
50
142
|
if (value != XT_UNDEFINED) return value;
|
|
51
143
|
}
|
|
52
|
-
|
|
144
|
+
/* Array.prototype[Symbol.iterator] is the fallback, after any own
|
|
145
|
+
* symbol property the program assigned. */
|
|
146
|
+
if (key == xt_symbol_well_known("iterator")) return xt_array_iterator_method();
|
|
147
|
+
xt_value method = xt_method_value(target, key);
|
|
148
|
+
if (method != XT_UNDEFINED) return method;
|
|
149
|
+
xt_value proto = ((xt_array *)XT_GET_PTR(target))->prototype;
|
|
150
|
+
if (proto != XT_UNDEFINED && proto != XT_NULL) return xt_get(proto, key);
|
|
151
|
+
return XT_UNDEFINED;
|
|
53
152
|
}
|
|
54
153
|
return xt_array_get(target, key);
|
|
55
154
|
}
|
|
@@ -69,6 +168,9 @@ xt_value xt_get(xt_value target, xt_value key) {
|
|
|
69
168
|
{
|
|
70
169
|
xt_value value = xt_object_get(target, key);
|
|
71
170
|
if (value != XT_UNDEFINED) return value;
|
|
171
|
+
/* `const A = Array; A.isArray`, `const S = Symbol; S.iterator`, ... */
|
|
172
|
+
value = xt_builtin_static_value(target, key);
|
|
173
|
+
if (value != XT_UNDEFINED) return value;
|
|
72
174
|
return xt_method_value(target, key);
|
|
73
175
|
}
|
|
74
176
|
}
|
|
@@ -76,6 +178,17 @@ xt_value xt_get(xt_value target, xt_value key) {
|
|
|
76
178
|
/* Map/Set expose `.size`; promises, dates and regexps have their own
|
|
77
179
|
* getters implemented in the standard library. */
|
|
78
180
|
xt_object *obj = (xt_object *)XT_GET_PTR(target);
|
|
181
|
+
if (obj->header.kind == XT_OBJECT_KIND_GENERATOR && xt_is_symbol(key)) {
|
|
182
|
+
/* Generators are iterable objects: `Symbol.iterator` returns the
|
|
183
|
+
* generator itself, and an async generator also exposes
|
|
184
|
+
* `Symbol.asyncIterator`. */
|
|
185
|
+
if (key == xt_symbol_well_known("asyncIterator") && xt_is_async_generator(target)) {
|
|
186
|
+
return xt_async_iterator_method();
|
|
187
|
+
}
|
|
188
|
+
if (key == xt_symbol_well_known("iterator") && !xt_is_async_generator(target)) {
|
|
189
|
+
return xt_async_iterator_method();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
79
192
|
if (obj->header.kind == XT_OBJECT_KIND_SYMBOL) {
|
|
80
193
|
if (XT_IS_STRING(key)) {
|
|
81
194
|
xt_string *k = xt_as_string(key);
|
|
@@ -83,7 +196,9 @@ xt_value xt_get(xt_value target, xt_value key) {
|
|
|
83
196
|
return xt_symbol_description(target);
|
|
84
197
|
}
|
|
85
198
|
}
|
|
86
|
-
|
|
199
|
+
xt_value method = xt_method_value(target, key);
|
|
200
|
+
if (method != XT_UNDEFINED) return method;
|
|
201
|
+
return xt_get_inherited(target, key);
|
|
87
202
|
}
|
|
88
203
|
if (obj->header.kind == XT_OBJECT_KIND_MAP || obj->header.kind == XT_OBJECT_KIND_SET) {
|
|
89
204
|
if (XT_IS_STRING(key)) {
|
|
@@ -107,27 +222,51 @@ xt_value xt_get(xt_value target, xt_value key) {
|
|
|
107
222
|
}
|
|
108
223
|
}
|
|
109
224
|
{
|
|
225
|
+
/* Typed arrays keep their elements in a shared ArrayBuffer: serve
|
|
226
|
+
* `.buffer` / element reads from it instead of the property bag. */
|
|
227
|
+
int typed = xt_typed_array_kind_of(target);
|
|
228
|
+
if (typed >= 0) {
|
|
229
|
+
if (XT_IS_STRING(key)) {
|
|
230
|
+
xt_string *k = xt_as_string(key);
|
|
231
|
+
if (k->length == 6 && memcmp(xt_string_bytes(k), "buffer", 6) == 0) {
|
|
232
|
+
return xt_typed_array_buffer_of(target);
|
|
233
|
+
}
|
|
234
|
+
if (k->length == 10 && memcmp(xt_string_bytes(k), "byteOffset", 10) == 0) {
|
|
235
|
+
return xt_number((double)xt_typed_array_byte_offset_of(target));
|
|
236
|
+
}
|
|
237
|
+
uint32_t index = 0;
|
|
238
|
+
if (xt_key_is_array_index(k, &index)) return xt_typed_array_read(target, index);
|
|
239
|
+
} else if (XT_IS_NUMBER(key)) {
|
|
240
|
+
int32_t index = xt_to_int32(key);
|
|
241
|
+
if (index >= 0) return xt_typed_array_read(target, (uint32_t)index);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
110
244
|
xt_value value = xt_object_get(target, key);
|
|
111
245
|
if (value != XT_UNDEFINED) return value;
|
|
112
|
-
|
|
246
|
+
xt_value method = xt_method_value(target, key);
|
|
247
|
+
if (method != XT_UNDEFINED) return method;
|
|
248
|
+
if (obj->header.kind != XT_OBJECT_KIND_OBJECT && obj->header.kind != XT_OBJECT_KIND_ERROR) {
|
|
249
|
+
return xt_get_inherited(target, key);
|
|
250
|
+
}
|
|
251
|
+
return XT_UNDEFINED;
|
|
113
252
|
}
|
|
114
253
|
}
|
|
115
254
|
if (XT_IS_STRING(target)) {
|
|
116
255
|
/* Property access on a string: `.length`, numeric indexing and built-in
|
|
117
|
-
* methods.
|
|
256
|
+
* methods. Indices are UTF-16 code units, so `s[0]` of a Chinese string is
|
|
257
|
+
* the whole character and an emoji index into its surrogate pair. */
|
|
118
258
|
xt_string *s = xt_as_string(target);
|
|
259
|
+
uint32_t units = xt_string_utf16_length(s);
|
|
119
260
|
if (XT_IS_STRING(key)) {
|
|
120
261
|
xt_string *k = xt_as_string(key);
|
|
121
|
-
if (k->length == 6 && memcmp(xt_string_bytes(k), "length", 6) == 0) return xt_number((double)
|
|
262
|
+
if (k->length == 6 && memcmp(xt_string_bytes(k), "length", 6) == 0) return xt_number((double)units);
|
|
122
263
|
uint32_t index = 0;
|
|
123
|
-
if (xt_key_is_array_index(k, &index) && index < s
|
|
124
|
-
return xt_string_new(xt_string_bytes(s) + index, 1);
|
|
125
|
-
}
|
|
264
|
+
if (xt_key_is_array_index(k, &index) && index < units) return xt_string_unit_value(s, (int32_t)index);
|
|
126
265
|
return xt_method_value(target, key);
|
|
127
266
|
}
|
|
128
267
|
if (XT_IS_NUMBER(key)) {
|
|
129
268
|
int32_t index = xt_to_int32(key);
|
|
130
|
-
if (index >= 0 && (uint32_t)index <
|
|
269
|
+
if (index >= 0 && (uint32_t)index < units) return xt_string_unit_value(s, index);
|
|
131
270
|
}
|
|
132
271
|
return XT_UNDEFINED;
|
|
133
272
|
}
|
|
@@ -138,6 +277,47 @@ xt_value xt_get(xt_value target, xt_value key) {
|
|
|
138
277
|
return XT_UNDEFINED;
|
|
139
278
|
}
|
|
140
279
|
|
|
280
|
+
/* Inline-cached property read. The generated code gives every source-level
|
|
281
|
+
* property access two zeroed i64 words; the first stores the receiver's shape
|
|
282
|
+
* and the second the property index. A shape hit is a pointer compare plus one
|
|
283
|
+
* key check, which avoids the linear property scan. Only ordinary objects and
|
|
284
|
+
* errors use the cache; arrays, functions, strings and containers fall back to
|
|
285
|
+
* the generic path. */
|
|
286
|
+
xt_value xt_get_ic(xt_value target, xt_value key, int64_t *cache) {
|
|
287
|
+
if (!cache || !XT_IS_OBJECT(target)) return xt_get(target, key);
|
|
288
|
+
xt_object *obj = (xt_object *)XT_GET_PTR(target);
|
|
289
|
+
if (obj->header.kind != XT_OBJECT_KIND_OBJECT && obj->header.kind != XT_OBJECT_KIND_ERROR) {
|
|
290
|
+
return xt_get(target, key);
|
|
291
|
+
}
|
|
292
|
+
if (!XT_IS_STRING(key) && !xt_is_symbol(key)) return xt_get(target, key);
|
|
293
|
+
xt_shape *shape = obj->shape;
|
|
294
|
+
uintptr_t cachedShape = (uintptr_t)cache[0];
|
|
295
|
+
int64_t cachedIndex = cache[1];
|
|
296
|
+
if (shape && cachedShape == (uintptr_t)shape && cachedIndex >= 0 &&
|
|
297
|
+
cachedIndex < (int64_t)obj->count) {
|
|
298
|
+
xt_property *prop = &obj->properties[cachedIndex];
|
|
299
|
+
if (prop->key == key || xt_property_key_equals(prop->key, key)) {
|
|
300
|
+
if (prop->getter != XT_UNDEFINED && XT_IS_FUNCTION(prop->getter)) {
|
|
301
|
+
return xt_call_with_this(prop->getter, target, 0, NULL);
|
|
302
|
+
}
|
|
303
|
+
if (prop->getter != XT_UNDEFINED) return XT_UNDEFINED;
|
|
304
|
+
return prop->value;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
xt_value propertyKey = xt_to_property_key(key);
|
|
308
|
+
xt_property *prop = xt_object_find_property(obj, propertyKey);
|
|
309
|
+
if (prop) {
|
|
310
|
+
cache[0] = (int64_t)(uintptr_t)shape;
|
|
311
|
+
cache[1] = (int64_t)(prop - obj->properties);
|
|
312
|
+
if (prop->getter != XT_UNDEFINED && XT_IS_FUNCTION(prop->getter)) {
|
|
313
|
+
return xt_call_with_this(prop->getter, target, 0, NULL);
|
|
314
|
+
}
|
|
315
|
+
if (prop->getter != XT_UNDEFINED) return XT_UNDEFINED;
|
|
316
|
+
return prop->value;
|
|
317
|
+
}
|
|
318
|
+
return xt_get(target, key);
|
|
319
|
+
}
|
|
320
|
+
|
|
141
321
|
xt_value xt_set(xt_value target, xt_value key, xt_value value) {
|
|
142
322
|
if (XT_IS_ARRAY(target)) {
|
|
143
323
|
/* Assigning `arr.length` truncates or extends the array. */
|
|
@@ -173,7 +353,7 @@ xt_value xt_set(xt_value target, xt_value key, xt_value value) {
|
|
|
173
353
|
if ((k->length == 6 && memcmp(xt_string_bytes(k), "length", 6) == 0) ||
|
|
174
354
|
(k->length == 10 && memcmp(xt_string_bytes(k), "byteLength", 10) == 0) ||
|
|
175
355
|
(k->length == 10 && memcmp(xt_string_bytes(k), "byteOffset", 10) == 0)) {
|
|
176
|
-
xt_throw(
|
|
356
|
+
xt_throw(xt_error_from_message("TypeError: Cannot assign to read only property"));
|
|
177
357
|
return value;
|
|
178
358
|
}
|
|
179
359
|
}
|
|
@@ -191,7 +371,8 @@ xt_value xt_set(xt_value target, xt_value key, xt_value value) {
|
|
|
191
371
|
if (isIndex) {
|
|
192
372
|
double length = xt_to_number(xt_object_get_cstr(target, "length"));
|
|
193
373
|
if (index >= (uint32_t)length) return value; /* out-of-bounds writes are ignored */
|
|
194
|
-
|
|
374
|
+
xt_typed_array_write(target, index, value);
|
|
375
|
+
return value;
|
|
195
376
|
}
|
|
196
377
|
}
|
|
197
378
|
return xt_object_set(target, key, value);
|
|
@@ -15,12 +15,20 @@ void xt_array_reserve(xt_array *array, uint32_t needed) {
|
|
|
15
15
|
array->capacity = capacity;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
/* Array.prototype: every ordinary array inherits from it. The prototype itself
|
|
19
|
+
* is an array, like ECMAScript, so `Array.isArray(Array.prototype)` holds. It
|
|
20
|
+
* is created with the ordinary object prototype as its own [[Prototype]], which
|
|
21
|
+
* terminates the array-specific link. */
|
|
22
|
+
static xt_value xt_array_proto_root = XT_UNDEFINED;
|
|
23
|
+
static int xt_array_proto_ready = 0;
|
|
24
|
+
|
|
25
|
+
static xt_value xt_array_new_with_proto(int32_t count, xt_value *items, xt_value proto) {
|
|
19
26
|
xt_array *array = (xt_array *)xt_alloc(sizeof(xt_array), XT_OBJECT_KIND_ARRAY);
|
|
20
27
|
array->length = 0;
|
|
21
28
|
array->capacity = 0;
|
|
22
29
|
array->items = NULL;
|
|
23
30
|
array->extra = XT_UNDEFINED;
|
|
31
|
+
array->prototype = proto;
|
|
24
32
|
if (count > 0) {
|
|
25
33
|
xt_array_reserve(array, (uint32_t)count);
|
|
26
34
|
for (int32_t i = 0; i < count; i++) array->items[i] = items[i];
|
|
@@ -29,6 +37,22 @@ xt_value xt_array_new(int32_t count, xt_value *items) {
|
|
|
29
37
|
return XT_FROM_PTR(XT_TAG_ARRAY, array);
|
|
30
38
|
}
|
|
31
39
|
|
|
40
|
+
xt_value xt_array_prototype(void) {
|
|
41
|
+
if (xt_array_proto_ready) return xt_array_proto_root;
|
|
42
|
+
xt_array_proto_ready = 1;
|
|
43
|
+
xt_array_proto_root = xt_array_new_with_proto(0, NULL, xt_object_prototype());
|
|
44
|
+
xt_gc_add_root(&xt_array_proto_root);
|
|
45
|
+
xt_value constructor = xt_builtin_constructor(xt_string_from_cstr("Array"));
|
|
46
|
+
if (constructor != XT_UNDEFINED) {
|
|
47
|
+
xt_set(xt_array_proto_root, xt_string_from_cstr("constructor"), constructor);
|
|
48
|
+
}
|
|
49
|
+
return xt_array_proto_root;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
xt_value xt_array_new(int32_t count, xt_value *items) {
|
|
53
|
+
return xt_array_new_with_proto(count, items, xt_array_prototype());
|
|
54
|
+
}
|
|
55
|
+
|
|
32
56
|
/* Named properties of an array live in a lazily-created side object. Returns
|
|
33
57
|
* XT_UNDEFINED when `create` is false and no such object exists yet. */
|
|
34
58
|
static xt_value xt_array_extra(xt_array *array, int create) {
|
|
@@ -69,7 +93,7 @@ xt_value xt_array_push(xt_value value, xt_value newValue) {
|
|
|
69
93
|
|
|
70
94
|
xt_value xt_array_length(xt_value value) {
|
|
71
95
|
if (XT_IS_ARRAY(value)) return xt_number((double)((xt_array *)XT_GET_PTR(value))->length);
|
|
72
|
-
if (XT_IS_STRING(value)) return xt_number((double)
|
|
96
|
+
if (XT_IS_STRING(value)) return xt_number((double)xt_string_utf16_length(xt_as_string(value)));
|
|
73
97
|
/* Functions expose their arity as `.length`. */
|
|
74
98
|
if (XT_IS_FUNCTION(value)) {
|
|
75
99
|
int32_t arity = ((xt_function *)XT_GET_PTR(value))->arity;
|
|
@@ -14,13 +14,159 @@ static void xt_object_reserve(xt_object *obj, uint32_t needed) {
|
|
|
14
14
|
obj->capacity = capacity;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
xt_value xt_object_new(void) { return xt_object_new_with_proto(
|
|
17
|
+
xt_value xt_object_new(void) { return xt_object_new_with_proto(xt_object_prototype()); }
|
|
18
|
+
|
|
19
|
+
/* ------------------------------------------------------------------------- */
|
|
20
|
+
/* Object.prototype */
|
|
21
|
+
/* ------------------------------------------------------------------------- */
|
|
22
|
+
|
|
23
|
+
/* `Object.prototype` is the root of the ordinary object prototype chain. Every
|
|
24
|
+
* plain object created by `xt_object_new` inherits from it, which is what makes
|
|
25
|
+
*
|
|
26
|
+
* Object.getPrototypeOf({}) === Object.prototype
|
|
27
|
+
* Object.prototype.hasOwnProperty.call(obj, key)
|
|
28
|
+
*
|
|
29
|
+
* hold. It is created lazily (and exactly once) with a null prototype, so the
|
|
30
|
+
* root itself terminates the chain. */
|
|
31
|
+
static xt_value xt_object_proto_root = XT_UNDEFINED;
|
|
32
|
+
static int xt_object_proto_ready = 0;
|
|
33
|
+
static xt_value xt_function_proto_root = XT_UNDEFINED;
|
|
34
|
+
static int xt_function_proto_ready = 0;
|
|
35
|
+
|
|
36
|
+
static const char *xt_object_tag_of(xt_value value) {
|
|
37
|
+
if (value == XT_UNDEFINED) return "Undefined";
|
|
38
|
+
if (value == XT_NULL) return "Null";
|
|
39
|
+
if (XT_IS_ARRAY(value)) return "Array";
|
|
40
|
+
if (XT_IS_FUNCTION(value)) return "Function";
|
|
41
|
+
if (XT_IS_STRING(value)) return "String";
|
|
42
|
+
if (XT_IS_BIGINT(value)) return "BigInt";
|
|
43
|
+
if (XT_IS_NUMBER(value)) return "Number";
|
|
44
|
+
if (value == XT_TRUE || value == XT_FALSE) return "Boolean";
|
|
45
|
+
if (XT_IS_OBJECT(value)) {
|
|
46
|
+
switch (((xt_object *)XT_GET_PTR(value))->header.kind) {
|
|
47
|
+
case XT_OBJECT_KIND_ERROR: return "Error";
|
|
48
|
+
case XT_OBJECT_KIND_MAP: return "Map";
|
|
49
|
+
case XT_OBJECT_KIND_SET: return "Set";
|
|
50
|
+
case XT_OBJECT_KIND_WEAK_MAP: return "WeakMap";
|
|
51
|
+
case XT_OBJECT_KIND_WEAK_SET: return "WeakSet";
|
|
52
|
+
case XT_OBJECT_KIND_WEAK_REF: return "WeakRef";
|
|
53
|
+
case XT_OBJECT_KIND_DATE: return "Date";
|
|
54
|
+
case XT_OBJECT_KIND_REGEXP: return "RegExp";
|
|
55
|
+
case XT_OBJECT_KIND_PROMISE: return "Promise";
|
|
56
|
+
case XT_OBJECT_KIND_SYMBOL: return "Symbol";
|
|
57
|
+
case XT_OBJECT_KIND_GENERATOR: return "Generator";
|
|
58
|
+
default: return "Object";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return "Object";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* Backing trampoline for the methods on `Object.prototype`. The method name
|
|
65
|
+
* travels in environment slot 0; `this` is the receiver, exactly like a
|
|
66
|
+
* JavaScript method. */
|
|
67
|
+
static xt_value xt_object_proto_method(xt_value thisValue, xt_value env, int32_t argc,
|
|
68
|
+
xt_value *argv) {
|
|
69
|
+
xt_value nameValue = xt_closure_env(env, 0);
|
|
70
|
+
const char *name = xt_string_data(nameValue);
|
|
71
|
+
if (!name) return XT_UNDEFINED;
|
|
72
|
+
if (strcmp(name, "hasOwnProperty") == 0) {
|
|
73
|
+
if (thisValue == XT_UNDEFINED || thisValue == XT_NULL) {
|
|
74
|
+
xt_throw(xt_error_from_message("TypeError: Cannot convert undefined or null to object"));
|
|
75
|
+
}
|
|
76
|
+
return xt_object_has_own(thisValue, xt_arg_at(argc, argv, 0));
|
|
77
|
+
}
|
|
78
|
+
if (strcmp(name, "propertyIsEnumerable") == 0) {
|
|
79
|
+
if (thisValue == XT_UNDEFINED || thisValue == XT_NULL) {
|
|
80
|
+
xt_throw(xt_error_from_message("TypeError: Cannot convert undefined or null to object"));
|
|
81
|
+
}
|
|
82
|
+
/* Enumerability is not tracked; every own property is enumerable. */
|
|
83
|
+
return xt_object_has_own(thisValue, xt_arg_at(argc, argv, 0));
|
|
84
|
+
}
|
|
85
|
+
if (strcmp(name, "toString") == 0) {
|
|
86
|
+
char buffer[64];
|
|
87
|
+
snprintf(buffer, sizeof(buffer), "[object %s]", xt_object_tag_of(thisValue));
|
|
88
|
+
return xt_string_from_cstr(buffer);
|
|
89
|
+
}
|
|
90
|
+
if (strcmp(name, "valueOf") == 0) return thisValue;
|
|
91
|
+
if (strcmp(name, "isPrototypeOf") == 0) {
|
|
92
|
+
xt_value cursor = xt_object_get_prototype(xt_arg_at(argc, argv, 0));
|
|
93
|
+
while (cursor != XT_UNDEFINED && cursor != XT_NULL) {
|
|
94
|
+
if (cursor == thisValue) return XT_TRUE;
|
|
95
|
+
cursor = xt_object_get_prototype(cursor);
|
|
96
|
+
}
|
|
97
|
+
return XT_FALSE;
|
|
98
|
+
}
|
|
99
|
+
if (strcmp(name, "__proto__") == 0) return xt_object_get_prototype(thisValue);
|
|
100
|
+
return XT_UNDEFINED;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* `__proto__ = value`: ordinary assignment through the inherited setter. */
|
|
104
|
+
static xt_value xt_object_proto_setter(xt_value thisValue, xt_value env, int32_t argc,
|
|
105
|
+
xt_value *argv) {
|
|
106
|
+
(void)env;
|
|
107
|
+
(void)argc;
|
|
108
|
+
xt_value proto = xt_arg_at(argc, argv, 0);
|
|
109
|
+
if (proto == XT_NULL || XT_IS_OBJECT(proto) || XT_IS_ARRAY(proto) || XT_IS_FUNCTION(proto)) {
|
|
110
|
+
xt_object_set_prototype(thisValue, proto);
|
|
111
|
+
}
|
|
112
|
+
return XT_UNDEFINED;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
static xt_value xt_object_proto_define(xt_value proto, const char *name, int32_t arity) {
|
|
116
|
+
xt_value env[1] = {xt_string_from_cstr(name)};
|
|
117
|
+
xt_value closure = xt_closure_new((void *)xt_object_proto_method, 1, env);
|
|
118
|
+
xt_function_set_metadata(closure, env[0], arity);
|
|
119
|
+
xt_object_set(proto, env[0], closure);
|
|
120
|
+
return closure;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
xt_value xt_function_prototype(void) {
|
|
124
|
+
if (xt_function_proto_ready) return xt_function_proto_root;
|
|
125
|
+
xt_function_proto_ready = 1;
|
|
126
|
+
xt_function_proto_root = xt_object_new_with_proto(xt_object_prototype());
|
|
127
|
+
xt_gc_add_root(&xt_function_proto_root);
|
|
128
|
+
/* `Array.constructor === Function` (every function inherits from here). The
|
|
129
|
+
* factory sees the ready flag, so this does not recurse. */
|
|
130
|
+
xt_value constructor = xt_builtin_constructor(xt_string_from_cstr("Function"));
|
|
131
|
+
if (constructor != XT_UNDEFINED) {
|
|
132
|
+
xt_object_set(xt_function_proto_root, xt_string_from_cstr("constructor"), constructor);
|
|
133
|
+
}
|
|
134
|
+
return xt_function_proto_root;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
xt_value xt_object_prototype(void) {
|
|
138
|
+
if (xt_object_proto_ready) return xt_object_proto_root;
|
|
139
|
+
xt_object_proto_ready = 1;
|
|
140
|
+
xt_object_proto_root = xt_object_new_with_proto(XT_NULL);
|
|
141
|
+
xt_gc_add_root(&xt_object_proto_root);
|
|
142
|
+
xt_object_proto_define(xt_object_proto_root, "hasOwnProperty", 1);
|
|
143
|
+
xt_object_proto_define(xt_object_proto_root, "propertyIsEnumerable", 1);
|
|
144
|
+
xt_object_proto_define(xt_object_proto_root, "isPrototypeOf", 1);
|
|
145
|
+
xt_object_proto_define(xt_object_proto_root, "toString", 0);
|
|
146
|
+
xt_object_proto_define(xt_object_proto_root, "valueOf", 0);
|
|
147
|
+
xt_value protoEnv[1] = {xt_string_from_cstr("__proto__")};
|
|
148
|
+
xt_value getter = xt_closure_new((void *)xt_object_proto_method, 1, protoEnv);
|
|
149
|
+
xt_value setter = xt_closure_new((void *)xt_object_proto_setter, 0, NULL);
|
|
150
|
+
xt_function_set_metadata(getter, protoEnv[0], 0);
|
|
151
|
+
xt_function_set_metadata(setter, protoEnv[0], 1);
|
|
152
|
+
xt_object_define_getter(xt_object_proto_root, protoEnv[0], getter);
|
|
153
|
+
xt_object_define_setter(xt_object_proto_root, protoEnv[0], setter);
|
|
154
|
+
/* `({}).constructor === Object`. The constructor factory calls back into
|
|
155
|
+
* `xt_object_prototype` while building the Object function, but the ready
|
|
156
|
+
* flag is already set and the root exists. */
|
|
157
|
+
xt_value constructor = xt_builtin_constructor(xt_string_from_cstr("Object"));
|
|
158
|
+
if (constructor != XT_UNDEFINED) {
|
|
159
|
+
xt_object_set(xt_object_proto_root, xt_string_from_cstr("constructor"), constructor);
|
|
160
|
+
}
|
|
161
|
+
return xt_object_proto_root;
|
|
162
|
+
}
|
|
18
163
|
|
|
19
164
|
xt_value xt_object_new_with_proto(xt_value proto) {
|
|
20
165
|
xt_object *obj = (xt_object *)xt_alloc(sizeof(xt_object), XT_OBJECT_KIND_OBJECT);
|
|
21
166
|
obj->count = 0;
|
|
22
167
|
obj->capacity = 0;
|
|
23
168
|
obj->properties = NULL;
|
|
169
|
+
obj->shape = xt_shape_empty();
|
|
24
170
|
obj->prototype = proto;
|
|
25
171
|
obj->frozen = 0;
|
|
26
172
|
obj->is_array_base = 0;
|
|
@@ -32,7 +178,7 @@ xt_object *xt_as_object(xt_value value) {
|
|
|
32
178
|
if (XT_IS_FUNCTION(value)) {
|
|
33
179
|
/* Functions carry their own property bag (used for static members). */
|
|
34
180
|
xt_function *fn = (xt_function *)XT_GET_PTR(value);
|
|
35
|
-
if (!fn->properties) fn->properties = (xt_object *)XT_GET_PTR(xt_object_new_with_proto(
|
|
181
|
+
if (!fn->properties) fn->properties = (xt_object *)XT_GET_PTR(xt_object_new_with_proto(xt_function_prototype()));
|
|
36
182
|
return fn->properties;
|
|
37
183
|
}
|
|
38
184
|
return NULL;
|
|
@@ -87,6 +233,7 @@ static xt_property *xt_object_insert_property(xt_object *obj, xt_value key) {
|
|
|
87
233
|
}
|
|
88
234
|
}
|
|
89
235
|
}
|
|
236
|
+
uint32_t oldCount = obj->count;
|
|
90
237
|
xt_object_reserve(obj, obj->count + 1);
|
|
91
238
|
for (uint32_t i = obj->count; i > position; i--) obj->properties[i] = obj->properties[i - 1];
|
|
92
239
|
xt_property *prop = &obj->properties[position];
|
|
@@ -95,6 +242,10 @@ static xt_property *xt_object_insert_property(xt_object *obj, xt_value key) {
|
|
|
95
242
|
prop->getter = XT_UNDEFINED;
|
|
96
243
|
prop->setter = XT_UNDEFINED;
|
|
97
244
|
obj->count++;
|
|
245
|
+
/* Appending follows a transition; inserting an integer key into the middle
|
|
246
|
+
* reorders the list, so rebuild the canonical shape from the new layout. */
|
|
247
|
+
if (position == oldCount && obj->shape) obj->shape = xt_shape_transition(obj->shape, key);
|
|
248
|
+
else xt_object_shape_changed(obj);
|
|
98
249
|
return prop;
|
|
99
250
|
}
|
|
100
251
|
|
|
@@ -224,12 +375,41 @@ xt_value xt_object_define_setter(xt_value value, xt_value key, xt_value setter)
|
|
|
224
375
|
}
|
|
225
376
|
|
|
226
377
|
xt_value xt_object_get_prototype(xt_value value) {
|
|
227
|
-
|
|
228
|
-
if (
|
|
378
|
+
if (XT_IS_ARRAY(value)) return ((xt_array *)XT_GET_PTR(value))->prototype;
|
|
379
|
+
if (XT_IS_FUNCTION(value)) {
|
|
380
|
+
/* A function's [[Prototype]] is the prototype of its property bag
|
|
381
|
+
* (`Function.prototype` unless `Object.setPrototypeOf` changed it). */
|
|
382
|
+
xt_object *bag = xt_as_object(value);
|
|
383
|
+
return bag ? bag->prototype : XT_UNDEFINED;
|
|
384
|
+
}
|
|
385
|
+
if (XT_IS_OBJECT(value)) {
|
|
386
|
+
xt_object *obj = (xt_object *)XT_GET_PTR(value);
|
|
387
|
+
switch (obj->header.kind) {
|
|
388
|
+
case XT_OBJECT_KIND_OBJECT:
|
|
389
|
+
case XT_OBJECT_KIND_ERROR:
|
|
390
|
+
return obj->prototype;
|
|
391
|
+
case XT_OBJECT_KIND_SYMBOL:
|
|
392
|
+
case XT_OBJECT_KIND_MAP:
|
|
393
|
+
case XT_OBJECT_KIND_SET:
|
|
394
|
+
case XT_OBJECT_KIND_WEAK_MAP:
|
|
395
|
+
case XT_OBJECT_KIND_WEAK_SET:
|
|
396
|
+
case XT_OBJECT_KIND_WEAK_REF:
|
|
397
|
+
case XT_OBJECT_KIND_DATE:
|
|
398
|
+
case XT_OBJECT_KIND_REGEXP:
|
|
399
|
+
case XT_OBJECT_KIND_PROMISE:
|
|
400
|
+
return xt_builtin_prototype_for_kind(obj->header.kind);
|
|
401
|
+
default:
|
|
402
|
+
return XT_UNDEFINED;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
229
405
|
return XT_UNDEFINED;
|
|
230
406
|
}
|
|
231
407
|
|
|
232
408
|
xt_value xt_object_set_prototype(xt_value value, xt_value proto) {
|
|
409
|
+
if (XT_IS_ARRAY(value)) {
|
|
410
|
+
((xt_array *)XT_GET_PTR(value))->prototype = proto;
|
|
411
|
+
return value;
|
|
412
|
+
}
|
|
233
413
|
xt_object *obj = xt_as_object(value);
|
|
234
414
|
if (obj && !obj->frozen) obj->prototype = proto;
|
|
235
415
|
return value;
|
|
@@ -247,8 +427,33 @@ int xt_object_is_frozen(xt_value value) {
|
|
|
247
427
|
}
|
|
248
428
|
|
|
249
429
|
xt_value xt_object_has_own(xt_value value, xt_value key) {
|
|
430
|
+
if (XT_IS_ARRAY(value)) {
|
|
431
|
+
xt_array *array = (xt_array *)XT_GET_PTR(value);
|
|
432
|
+
xt_value propertyKey = xt_to_property_key(key);
|
|
433
|
+
if (XT_IS_STRING(propertyKey)) {
|
|
434
|
+
xt_string *k = xt_as_string(propertyKey);
|
|
435
|
+
if (k->length == 6 && memcmp(xt_string_bytes(k), "length", 6) == 0) return XT_TRUE;
|
|
436
|
+
uint32_t index = 0;
|
|
437
|
+
if (xt_key_is_array_index(k, &index)) return xt_bool(index < array->length);
|
|
438
|
+
}
|
|
439
|
+
return xt_bool(XT_IS_OBJECT(array->extra) &&
|
|
440
|
+
xt_object_find((xt_object *)XT_GET_PTR(array->extra), propertyKey));
|
|
441
|
+
}
|
|
442
|
+
if (XT_IS_STRING(value)) {
|
|
443
|
+
xt_string *string = xt_as_string(value);
|
|
444
|
+
if (xt_is_symbol(key)) return XT_FALSE;
|
|
445
|
+
xt_string *k = xt_as_string(xt_to_string(key));
|
|
446
|
+
if (k->length == 6 && memcmp(xt_string_bytes(k), "length", 6) == 0) return XT_TRUE;
|
|
447
|
+
uint32_t index = 0;
|
|
448
|
+
return xt_bool(xt_key_is_array_index(k, &index) && index < xt_string_utf16_length(string));
|
|
449
|
+
}
|
|
250
450
|
xt_object *obj = xt_as_object(value);
|
|
251
451
|
if (!obj) return XT_FALSE;
|
|
452
|
+
/* Map/Set/Date/RegExp/Promise/Symbol use their own struct layout and have no
|
|
453
|
+
* property bag; interpreting them as `xt_object` would read past the end. */
|
|
454
|
+
if (obj->header.kind != XT_OBJECT_KIND_OBJECT && obj->header.kind != XT_OBJECT_KIND_ERROR) {
|
|
455
|
+
return XT_FALSE;
|
|
456
|
+
}
|
|
252
457
|
return xt_bool(xt_object_find(obj, xt_to_property_key(key)) != NULL);
|
|
253
458
|
}
|
|
254
459
|
|
|
@@ -267,6 +472,9 @@ xt_value xt_object_from_entries(xt_value entries) {
|
|
|
267
472
|
xt_value xt_object_has(xt_value value, xt_value key) {
|
|
268
473
|
if (!XT_IS_OBJECT(value)) return XT_FALSE;
|
|
269
474
|
xt_object *obj = (xt_object *)XT_GET_PTR(value);
|
|
475
|
+
if (obj->header.kind != XT_OBJECT_KIND_OBJECT && obj->header.kind != XT_OBJECT_KIND_ERROR) {
|
|
476
|
+
return XT_FALSE;
|
|
477
|
+
}
|
|
270
478
|
return xt_bool(xt_object_find(obj, xt_to_property_key(key)) != NULL);
|
|
271
479
|
}
|
|
272
480
|
|
|
@@ -286,6 +494,18 @@ xt_value xt_object_own_property_symbols(xt_value value) {
|
|
|
286
494
|
|
|
287
495
|
xt_value xt_object_keys(xt_value value) {
|
|
288
496
|
xt_value result = xt_array_new(0, NULL);
|
|
497
|
+
/* A typed array's enumerable own keys are its indices; `length` and the
|
|
498
|
+
* buffer metadata are observable but not enumerable. */
|
|
499
|
+
int typed = xt_typed_array_kind_of(value);
|
|
500
|
+
if (typed >= 0) {
|
|
501
|
+
uint32_t length = (uint32_t)xt_to_number(xt_object_get_cstr(value, "length"));
|
|
502
|
+
for (uint32_t i = 0; i < length; i++) {
|
|
503
|
+
char buffer[32];
|
|
504
|
+
snprintf(buffer, sizeof(buffer), "%u", i);
|
|
505
|
+
xt_array_push(result, xt_string_from_cstr(buffer));
|
|
506
|
+
}
|
|
507
|
+
return result;
|
|
508
|
+
}
|
|
289
509
|
if (XT_IS_OBJECT(value)) {
|
|
290
510
|
xt_object *obj = (xt_object *)XT_GET_PTR(value);
|
|
291
511
|
for (uint32_t i = 0; i < obj->count; i++) {
|
|
@@ -310,7 +530,8 @@ xt_value xt_object_keys(xt_value value) {
|
|
|
310
530
|
}
|
|
311
531
|
if (XT_IS_STRING(value)) {
|
|
312
532
|
xt_string *s = xt_as_string(value);
|
|
313
|
-
|
|
533
|
+
uint32_t units = xt_string_utf16_length(s);
|
|
534
|
+
for (uint32_t i = 0; i < units; i++) {
|
|
314
535
|
char buffer[32];
|
|
315
536
|
snprintf(buffer, sizeof(buffer), "%u", i);
|
|
316
537
|
xt_array_push(result, xt_string_from_cstr(buffer));
|