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
|
@@ -26,6 +26,8 @@ static xt_value xt_error_proto_for(const char *name) {
|
|
|
26
26
|
xt_string_from_cstr("Error"));
|
|
27
27
|
xt_object_set(xt_error_root_proto, xt_string_from_cstr("message"),
|
|
28
28
|
xt_string_from_cstr(""));
|
|
29
|
+
xt_value constructor = xt_error_constructor(xt_string_from_cstr("Error"));
|
|
30
|
+
xt_object_set(xt_error_root_proto, xt_string_from_cstr("constructor"), constructor);
|
|
29
31
|
}
|
|
30
32
|
if (strcmp(name, "Error") == 0) return xt_error_root_proto;
|
|
31
33
|
xt_value key = xt_string_from_cstr(name);
|
|
@@ -41,6 +43,8 @@ static xt_value xt_error_proto_for(const char *name) {
|
|
|
41
43
|
xt_object_set(proto, xt_string_from_cstr("name"), key);
|
|
42
44
|
xt_object_set(proto, xt_string_from_cstr("message"), xt_string_from_cstr(""));
|
|
43
45
|
xt_object_set(registry, key, proto);
|
|
46
|
+
xt_value constructor = xt_error_constructor(key);
|
|
47
|
+
xt_object_set(proto, xt_string_from_cstr("constructor"), constructor);
|
|
44
48
|
return proto;
|
|
45
49
|
}
|
|
46
50
|
|
|
@@ -108,6 +112,30 @@ xt_value xt_error_constructor(xt_value nameValue) {
|
|
|
108
112
|
return closure;
|
|
109
113
|
}
|
|
110
114
|
|
|
115
|
+
/* Build the value thrown by the runtime for an internal "Name: message"
|
|
116
|
+
* string. JavaScript code can observe anything thrown, so internal failures
|
|
117
|
+
* must be real Error instances (`instanceof Error`, `.name`, `.message`,
|
|
118
|
+
* `.stack`), exactly like `new TypeError("...")`; a bare string would make
|
|
119
|
+
* `catch` blocks silently misbehave. User `throw` expressions never go
|
|
120
|
+
* through this helper. */
|
|
121
|
+
xt_value xt_error_from_message(const char *message) {
|
|
122
|
+
const char *separator = strstr(message, ": ");
|
|
123
|
+
if (separator != NULL) {
|
|
124
|
+
size_t nameLength = (size_t)(separator - message);
|
|
125
|
+
char name[24];
|
|
126
|
+
if (nameLength > 0 && nameLength < sizeof(name)) {
|
|
127
|
+
memcpy(name, message, nameLength);
|
|
128
|
+
name[nameLength] = '\0';
|
|
129
|
+
if (xt_error_is_family(name)) {
|
|
130
|
+
xt_value argument = xt_string_from_cstr(separator + 2);
|
|
131
|
+
return xt_make_error(name, 1, &argument);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
xt_value argument = xt_string_from_cstr(message);
|
|
136
|
+
return xt_make_error("Error", 1, &argument);
|
|
137
|
+
}
|
|
138
|
+
|
|
111
139
|
xt_value xt_error_to_string(xt_value error) {
|
|
112
140
|
xt_value name = xt_object_get(error, xt_string_from_cstr("name"));
|
|
113
141
|
xt_value message = xt_object_get(error, xt_string_from_cstr("message"));
|
|
@@ -162,6 +190,13 @@ xt_value xt_aggregate_error_ctor(int32_t argc, xt_value *argv) {
|
|
|
162
190
|
return xt_make_error("AggregateError", argc, argv);
|
|
163
191
|
}
|
|
164
192
|
|
|
193
|
+
/* Dispatch used by the first-class constructor factory (`const E = TypeError`). */
|
|
194
|
+
xt_value xt_error_ctor_by_name(xt_value nameValue, int32_t argc, xt_value *argv) {
|
|
195
|
+
const char *name = XT_IS_STRING(nameValue) ? xt_string_data(nameValue) : "Error";
|
|
196
|
+
if (!xt_error_is_family(name)) name = "Error";
|
|
197
|
+
return xt_make_error(name, argc, argv);
|
|
198
|
+
}
|
|
199
|
+
|
|
165
200
|
/* `super(message)` inside a subclass of the builtin Error family: initialize
|
|
166
201
|
* the already-allocated instance instead of creating a fresh object. The
|
|
167
202
|
* parent's name selects the default `name` (`TypeError`, ...). */
|
|
@@ -36,14 +36,31 @@ static xt_value xt_json_parse_string(xt_json_cursor *c) {
|
|
|
36
36
|
else if (h >= 'a' && h <= 'f') code |= (unsigned)(h - 'a' + 10);
|
|
37
37
|
else if (h >= 'A' && h <= 'F') code |= (unsigned)(h - 'A' + 10);
|
|
38
38
|
}
|
|
39
|
+
/* A high surrogate followed by `\u` and a low surrogate denotes one
|
|
40
|
+
* supplementary code point, exactly like a JavaScript string. */
|
|
41
|
+
if (code >= 0xD800 && code <= 0xDBFF && c->pos + 5 < c->length &&
|
|
42
|
+
c->data[c->pos] == '\\' && c->data[c->pos + 1] == 'u') {
|
|
43
|
+
unsigned low = 0;
|
|
44
|
+
int valid = 1;
|
|
45
|
+
for (int i = 0; i < 4; i++) {
|
|
46
|
+
char h = c->data[c->pos + 2 + (size_t)i];
|
|
47
|
+
low <<= 4;
|
|
48
|
+
if (h >= '0' && h <= '9') low |= (unsigned)(h - '0');
|
|
49
|
+
else if (h >= 'a' && h <= 'f') low |= (unsigned)(h - 'a' + 10);
|
|
50
|
+
else if (h >= 'A' && h <= 'F') low |= (unsigned)(h - 'A' + 10);
|
|
51
|
+
else valid = 0;
|
|
52
|
+
}
|
|
53
|
+
if (valid && low >= 0xDC00 && low <= 0xDFFF) {
|
|
54
|
+
code = 0x10000 + ((code - 0xD800) << 10) + (low - 0xDC00);
|
|
55
|
+
c->pos += 6;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
39
58
|
if (code >= 0x80) {
|
|
40
59
|
char tmp[4];
|
|
41
|
-
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
memcpy(out + length, tmp, (size_t)bytes);
|
|
46
|
-
length += (size_t)bytes;
|
|
60
|
+
size_t bytes = xt_utf8_encode(code, tmp);
|
|
61
|
+
if (length + bytes + 1 > capacity) { capacity = (length + bytes + 1) * 2; out = (char *)realloc(out, capacity); if (!out) abort(); }
|
|
62
|
+
memcpy(out + length, tmp, bytes);
|
|
63
|
+
length += bytes;
|
|
47
64
|
continue;
|
|
48
65
|
}
|
|
49
66
|
ch = (char)code;
|
|
@@ -116,50 +133,152 @@ static xt_value xt_json_parse_value(xt_json_cursor *c) {
|
|
|
116
133
|
return xt_json_parse_number(c);
|
|
117
134
|
}
|
|
118
135
|
|
|
136
|
+
/* Reviver walk: rebuild each container bottom-up, then pass the value to the
|
|
137
|
+
* user callback with its holder as `this`. Returning undefined deletes an
|
|
138
|
+
* object property / array element, exactly like the specification. */
|
|
139
|
+
static xt_value xt_json_revive(xt_value holder, xt_value key, xt_value reviver) {
|
|
140
|
+
xt_value value = xt_get(holder, key);
|
|
141
|
+
if (XT_IS_ARRAY(value)) {
|
|
142
|
+
xt_array *array = xt_as_array(value);
|
|
143
|
+
for (uint32_t i = 0; i < array->length; i++) {
|
|
144
|
+
/* Reviver keys are strings even for array indices. */
|
|
145
|
+
char keyBuffer[16];
|
|
146
|
+
snprintf(keyBuffer, sizeof(keyBuffer), "%u", i);
|
|
147
|
+
xt_value index = xt_string_from_cstr(keyBuffer);
|
|
148
|
+
xt_value updated = xt_json_revive(value, index, reviver);
|
|
149
|
+
if (updated == XT_UNDEFINED) xt_delete(value, index);
|
|
150
|
+
else xt_set(value, index, updated);
|
|
151
|
+
}
|
|
152
|
+
} else if (XT_IS_OBJECT(value)) {
|
|
153
|
+
xt_value keys = xt_object_keys(value);
|
|
154
|
+
xt_array *list = xt_as_array(keys);
|
|
155
|
+
if (list) {
|
|
156
|
+
for (uint32_t i = 0; i < list->length; i++) {
|
|
157
|
+
xt_value childKey = list->items[i];
|
|
158
|
+
xt_value updated = xt_json_revive(value, childKey, reviver);
|
|
159
|
+
if (updated == XT_UNDEFINED) xt_delete(value, childKey);
|
|
160
|
+
else xt_object_set(value, childKey, updated);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
xt_value args[2] = {key, value};
|
|
165
|
+
return xt_call_with_this(reviver, holder, 2, args);
|
|
166
|
+
}
|
|
167
|
+
|
|
119
168
|
xt_value xt_json_parse(int32_t argc, xt_value *argv) {
|
|
120
169
|
xt_value input = xt_to_string(xt_arg_at(argc, argv, 0));
|
|
121
170
|
xt_string *s = xt_as_string(input);
|
|
122
171
|
if (!s) return XT_UNDEFINED;
|
|
123
172
|
xt_json_cursor cursor = {xt_string_bytes(s), s->length, 0};
|
|
124
|
-
|
|
173
|
+
xt_value parsed = xt_json_parse_value(&cursor);
|
|
174
|
+
xt_value reviver = xt_arg_at(argc, argv, 1);
|
|
175
|
+
if (!XT_IS_FUNCTION(reviver)) return parsed;
|
|
176
|
+
xt_value holder = xt_object_new();
|
|
177
|
+
xt_object_set(holder, xt_string_from_cstr(""), parsed);
|
|
178
|
+
return xt_json_revive(holder, xt_string_from_cstr(""), reviver);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
static void xt_json_stringify_value(xt_value value, xt_value indent, int depth, xt_value *out);
|
|
182
|
+
|
|
183
|
+
/* The indentation unit for the `space` argument: up to 10 spaces for a
|
|
184
|
+
* number, or the first 10 UTF-16 code units of a string (any characters,
|
|
185
|
+
* not just spaces), matching JSON.stringify. An empty string means compact. */
|
|
186
|
+
static xt_value xt_json_space_unit(xt_value space) {
|
|
187
|
+
if (XT_IS_NUMBER(space)) {
|
|
188
|
+
int count = xt_to_int32(space);
|
|
189
|
+
if (count < 0) count = 0;
|
|
190
|
+
if (count > 10) count = 10;
|
|
191
|
+
char spaces[10];
|
|
192
|
+
memset(spaces, ' ', (size_t)count);
|
|
193
|
+
return xt_string_new(spaces, (size_t)count);
|
|
194
|
+
}
|
|
195
|
+
if (XT_IS_STRING(space)) {
|
|
196
|
+
xt_string *s = xt_as_string(space);
|
|
197
|
+
const char *bytes = xt_string_bytes(s);
|
|
198
|
+
size_t offset = 0;
|
|
199
|
+
size_t end = 0;
|
|
200
|
+
uint32_t units = 0;
|
|
201
|
+
while (offset < s->length && units < 10) {
|
|
202
|
+
size_t width = 0;
|
|
203
|
+
uint32_t code = xt_utf8_decode(bytes + offset, s->length - offset, &width);
|
|
204
|
+
units += code >= 0x10000 ? 2 : 1;
|
|
205
|
+
offset += width;
|
|
206
|
+
if (units <= 10) end = offset;
|
|
207
|
+
}
|
|
208
|
+
return xt_string_new(bytes, end);
|
|
209
|
+
}
|
|
210
|
+
return xt_string_from_cstr("");
|
|
125
211
|
}
|
|
126
212
|
|
|
127
|
-
static
|
|
213
|
+
static int xt_json_indented(xt_value unit) {
|
|
214
|
+
return XT_IS_STRING(unit) && xt_as_string(unit)->length > 0;
|
|
215
|
+
}
|
|
128
216
|
|
|
129
|
-
static void xt_json_indent(xt_value *out,
|
|
130
|
-
if (
|
|
217
|
+
static void xt_json_indent(xt_value *out, xt_value unit, int depth) {
|
|
218
|
+
if (!xt_json_indented(unit)) return;
|
|
131
219
|
*out = xt_add(*out, xt_string_from_cstr("\n"));
|
|
132
|
-
for (int i = 0; i <
|
|
220
|
+
for (int i = 0; i < depth; i++) *out = xt_add(*out, unit);
|
|
133
221
|
}
|
|
134
222
|
|
|
135
|
-
|
|
223
|
+
/* Containers on the current serialization path. A repeated pointer is a cycle;
|
|
224
|
+
* serializing it would recurse until the native stack overflowed (a hard crash,
|
|
225
|
+
* not the TypeError the platform throws). */
|
|
226
|
+
static xt_value *xt_json_path = NULL;
|
|
227
|
+
static uint32_t xt_json_path_count = 0;
|
|
228
|
+
static uint32_t xt_json_path_capacity = 0;
|
|
229
|
+
|
|
230
|
+
static void xt_json_enter(xt_value value) {
|
|
231
|
+
for (uint32_t i = 0; i < xt_json_path_count; i++) {
|
|
232
|
+
if (xt_json_path[i] == value) {
|
|
233
|
+
xt_value message = xt_string_from_cstr("Converting circular structure to JSON");
|
|
234
|
+
xt_throw(xt_type_error_ctor(1, &message));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (xt_json_path_count >= xt_json_path_capacity) {
|
|
238
|
+
uint32_t capacity = xt_json_path_capacity == 0 ? 16 : xt_json_path_capacity * 2;
|
|
239
|
+
xt_value *path = (xt_value *)realloc(xt_json_path, sizeof(xt_value) * capacity);
|
|
240
|
+
if (!path) abort();
|
|
241
|
+
xt_json_path = path;
|
|
242
|
+
xt_json_path_capacity = capacity;
|
|
243
|
+
}
|
|
244
|
+
xt_json_path[xt_json_path_count++] = value;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
static void xt_json_leave(void) {
|
|
248
|
+
if (xt_json_path_count > 0) xt_json_path_count--;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
static void xt_json_stringify_array(xt_value value, xt_value indent, int depth, xt_value *out) {
|
|
136
252
|
xt_array *array = xt_as_array(value);
|
|
137
253
|
if (!array || array->length == 0) { *out = xt_add(*out, xt_string_from_cstr("[]")); return; }
|
|
138
254
|
*out = xt_add(*out, xt_string_from_cstr("["));
|
|
255
|
+
xt_json_enter(value);
|
|
139
256
|
for (uint32_t i = 0; i < array->length; i++) {
|
|
140
257
|
if (i > 0) *out = xt_add(*out, xt_string_from_cstr(","));
|
|
141
258
|
xt_json_indent(out, indent, depth + 1);
|
|
142
259
|
xt_json_stringify_value(array->items[i], indent, depth + 1, out);
|
|
143
260
|
}
|
|
144
261
|
xt_json_indent(out, indent, depth);
|
|
262
|
+
xt_json_leave();
|
|
145
263
|
*out = xt_add(*out, xt_string_from_cstr("]"));
|
|
146
264
|
}
|
|
147
265
|
|
|
148
|
-
static void xt_json_stringify_object(xt_value value,
|
|
266
|
+
static void xt_json_stringify_object(xt_value value, xt_value indent, int depth, xt_value *out) {
|
|
149
267
|
xt_value keys = xt_object_keys(value);
|
|
150
268
|
xt_array *array = xt_as_array(keys);
|
|
151
269
|
if (!array) { *out = xt_add(*out, xt_string_from_cstr("{}")); return; }
|
|
152
270
|
int any = 0;
|
|
153
271
|
for (uint32_t i = 0; i < array->length; i++) {
|
|
154
|
-
xt_value item =
|
|
272
|
+
xt_value item = xt_get(value, array->items[i]);
|
|
155
273
|
if (item != XT_UNDEFINED && !XT_IS_FUNCTION(item) && !xt_is_symbol(item)) { any = 1; break; }
|
|
156
274
|
}
|
|
157
275
|
if (!any) { *out = xt_add(*out, xt_string_from_cstr("{}")); return; }
|
|
158
276
|
*out = xt_add(*out, xt_string_from_cstr("{"));
|
|
277
|
+
xt_json_enter(value);
|
|
159
278
|
int written = 0;
|
|
160
279
|
for (uint32_t i = 0; i < array->length; i++) {
|
|
161
280
|
xt_value key = array->items[i];
|
|
162
|
-
xt_value item =
|
|
281
|
+
xt_value item = xt_get(value, key);
|
|
163
282
|
/* `undefined`, functions and symbols are omitted from objects. */
|
|
164
283
|
if (item == XT_UNDEFINED || XT_IS_FUNCTION(item) || xt_is_symbol(item)) continue;
|
|
165
284
|
if (written > 0) *out = xt_add(*out, xt_string_from_cstr(","));
|
|
@@ -168,20 +287,21 @@ static void xt_json_stringify_object(xt_value value, int indent, int depth, xt_v
|
|
|
168
287
|
*out = xt_add(*out, xt_string_from_cstr("\""));
|
|
169
288
|
*out = xt_add(*out, key);
|
|
170
289
|
*out = xt_add(*out, xt_string_from_cstr("\":"));
|
|
171
|
-
if (indent
|
|
290
|
+
if (xt_json_indented(indent)) *out = xt_add(*out, xt_string_from_cstr(" "));
|
|
172
291
|
xt_json_stringify_value(item, indent, depth + 1, out);
|
|
173
292
|
}
|
|
174
293
|
xt_json_indent(out, indent, depth);
|
|
294
|
+
xt_json_leave();
|
|
175
295
|
*out = xt_add(*out, xt_string_from_cstr("}"));
|
|
176
296
|
}
|
|
177
297
|
|
|
178
|
-
static void xt_json_stringify_value(xt_value value,
|
|
298
|
+
static void xt_json_stringify_value(xt_value value, xt_value indent, int depth, xt_value *out) {
|
|
179
299
|
if (value == XT_UNDEFINED || value == XT_NULL || XT_IS_FUNCTION(value) || xt_is_symbol(value)) {
|
|
180
300
|
*out = xt_add(*out, xt_string_from_cstr("null"));
|
|
181
301
|
return;
|
|
182
302
|
}
|
|
183
303
|
if (XT_IS_BIGINT(value)) {
|
|
184
|
-
xt_throw(
|
|
304
|
+
xt_throw(xt_error_from_message("TypeError: Do not know how to serialize a BigInt"));
|
|
185
305
|
return;
|
|
186
306
|
}
|
|
187
307
|
if (XT_IS_BOOL(value)) { *out = xt_add(*out, value == XT_TRUE ? xt_string_from_cstr("true") : xt_string_from_cstr("false")); return; }
|
|
@@ -195,32 +315,232 @@ static void xt_json_stringify_value(xt_value value, int indent, int depth, xt_va
|
|
|
195
315
|
xt_string *s = xt_as_string(value);
|
|
196
316
|
const char *bytes = xt_string_bytes(s);
|
|
197
317
|
*out = xt_add(*out, xt_string_from_cstr("\""));
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
else
|
|
318
|
+
size_t offset = 0;
|
|
319
|
+
while (offset < s->length) {
|
|
320
|
+
size_t width = 0;
|
|
321
|
+
uint32_t code = xt_utf8_decode(bytes + offset, s->length - offset, &width);
|
|
322
|
+
const char *escape = NULL;
|
|
323
|
+
char buffer[8];
|
|
324
|
+
if (code == '"') escape = "\\\"";
|
|
325
|
+
else if (code == '\\') escape = "\\\\";
|
|
326
|
+
else if (code == '\b') escape = "\\b";
|
|
327
|
+
else if (code == '\f') escape = "\\f";
|
|
328
|
+
else if (code == '\n') escape = "\\n";
|
|
329
|
+
else if (code == '\r') escape = "\\r";
|
|
330
|
+
else if (code == '\t') escape = "\\t";
|
|
331
|
+
else if (code < 0x20 || (code >= 0xD800 && code <= 0xDFFF)) {
|
|
332
|
+
snprintf(buffer, sizeof(buffer), "\\u%04x", (unsigned)code);
|
|
333
|
+
escape = buffer;
|
|
334
|
+
}
|
|
335
|
+
if (escape) *out = xt_add(*out, xt_string_from_cstr(escape));
|
|
336
|
+
else *out = xt_add(*out, xt_string_new(bytes + offset, width));
|
|
337
|
+
offset += width;
|
|
206
338
|
}
|
|
207
339
|
*out = xt_add(*out, xt_string_from_cstr("\""));
|
|
208
340
|
return;
|
|
209
341
|
}
|
|
210
342
|
if (XT_IS_ARRAY(value)) { xt_json_stringify_array(value, indent, depth, out); return; }
|
|
211
|
-
if (XT_IS_OBJECT(value)) {
|
|
343
|
+
if (XT_IS_OBJECT(value)) {
|
|
344
|
+
/* Map/Set/Date/RegExp/Promise/generators are not property-bag objects;
|
|
345
|
+
* handing them to xt_json_stringify_object reads their fields as a property
|
|
346
|
+
* table and crashed with an access violation. JSON sees no enumerable own
|
|
347
|
+
* properties on the first group and calls Date.prototype.toJSON. */
|
|
348
|
+
xt_object *object = (xt_object *)XT_GET_PTR(value);
|
|
349
|
+
switch (object->header.kind) {
|
|
350
|
+
case XT_OBJECT_KIND_MAP:
|
|
351
|
+
case XT_OBJECT_KIND_SET:
|
|
352
|
+
case XT_OBJECT_KIND_REGEXP:
|
|
353
|
+
case XT_OBJECT_KIND_PROMISE:
|
|
354
|
+
case XT_OBJECT_KIND_GENERATOR:
|
|
355
|
+
case XT_OBJECT_KIND_ITERATOR:
|
|
356
|
+
case XT_OBJECT_KIND_ASYNC:
|
|
357
|
+
*out = xt_add(*out, xt_string_from_cstr("{}"));
|
|
358
|
+
return;
|
|
359
|
+
case XT_OBJECT_KIND_DATE: {
|
|
360
|
+
xt_value time = xt_call_method(value, xt_string_from_cstr("getTime"), 0, NULL);
|
|
361
|
+
if (isnan(xt_to_number(time))) {
|
|
362
|
+
*out = xt_add(*out, xt_string_from_cstr("null"));
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
xt_value text = xt_call_method(value, xt_string_from_cstr("toJSON"), 0, NULL);
|
|
366
|
+
xt_json_stringify_value(text, indent, depth, out);
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
default:
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
xt_json_stringify_object(value, indent, depth, out);
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
212
375
|
*out = xt_add(*out, xt_string_from_cstr("null"));
|
|
213
376
|
}
|
|
214
377
|
|
|
378
|
+
/* -- replacer-aware stringify -------------------------------------------- */
|
|
379
|
+
/*
|
|
380
|
+
* The replacer overload needs the holder and key of every value, so it gets a
|
|
381
|
+
* separate walk instead of complicating the fast path. It also calls `toJSON`
|
|
382
|
+
* and filters object keys through an array replacer.
|
|
383
|
+
*/
|
|
384
|
+
typedef struct {
|
|
385
|
+
xt_value replacer;
|
|
386
|
+
xt_value indent;
|
|
387
|
+
xt_value *path;
|
|
388
|
+
uint32_t path_count;
|
|
389
|
+
uint32_t path_capacity;
|
|
390
|
+
} xt_json_replacer_context;
|
|
391
|
+
|
|
392
|
+
static void xt_json_replacer_enter(xt_json_replacer_context *ctx, xt_value value) {
|
|
393
|
+
for (uint32_t i = 0; i < ctx->path_count; i++) {
|
|
394
|
+
if (ctx->path[i] == value) {
|
|
395
|
+
xt_value message = xt_string_from_cstr("Converting circular structure to JSON");
|
|
396
|
+
xt_throw(xt_type_error_ctor(1, &message));
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (ctx->path_count >= ctx->path_capacity) {
|
|
400
|
+
uint32_t capacity = ctx->path_capacity == 0 ? 16 : ctx->path_capacity * 2;
|
|
401
|
+
xt_value *path = (xt_value *)realloc(ctx->path, sizeof(xt_value) * capacity);
|
|
402
|
+
if (!path) abort();
|
|
403
|
+
ctx->path = path;
|
|
404
|
+
ctx->path_capacity = capacity;
|
|
405
|
+
}
|
|
406
|
+
ctx->path[ctx->path_count++] = value;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
static void xt_json_replacer_leave(xt_json_replacer_context *ctx) {
|
|
410
|
+
if (ctx->path_count > 0) ctx->path_count--;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
static void xt_json_replacer_indent(xt_json_replacer_context *ctx, int depth, xt_value *out) {
|
|
414
|
+
xt_json_indent(out, ctx->indent, depth);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
static int xt_json_replacer_allows(xt_value replacer, xt_value key) {
|
|
418
|
+
if (!XT_IS_ARRAY(replacer)) return 1;
|
|
419
|
+
xt_array *allowed = xt_as_array(replacer);
|
|
420
|
+
for (uint32_t i = 0; i < allowed->length; i++) {
|
|
421
|
+
xt_value item = allowed->items[i];
|
|
422
|
+
if (!XT_IS_STRING(item) && !XT_IS_NUMBER(item)) continue;
|
|
423
|
+
xt_value text = xt_to_string(item);
|
|
424
|
+
xt_string *a = xt_as_string(text);
|
|
425
|
+
xt_string *b = xt_as_string(key);
|
|
426
|
+
if (a && b && xt_string_equals(a, b)) return 1;
|
|
427
|
+
}
|
|
428
|
+
return 0;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
static int xt_json_replacer_write(xt_json_replacer_context *ctx, xt_value holder, xt_value key,
|
|
432
|
+
int depth, xt_value *out);
|
|
433
|
+
|
|
434
|
+
static int xt_json_replacer_container(xt_json_replacer_context *ctx, xt_value value, int depth,
|
|
435
|
+
xt_value *out) {
|
|
436
|
+
xt_json_replacer_enter(ctx, value);
|
|
437
|
+
if (XT_IS_ARRAY(value)) {
|
|
438
|
+
xt_array *array = xt_as_array(value);
|
|
439
|
+
*out = xt_add(*out, xt_string_from_cstr("["));
|
|
440
|
+
for (uint32_t i = 0; i < array->length; i++) {
|
|
441
|
+
if (i > 0) *out = xt_add(*out, xt_string_from_cstr(","));
|
|
442
|
+
xt_json_replacer_indent(ctx, depth + 1, out);
|
|
443
|
+
char keyBuffer[16];
|
|
444
|
+
snprintf(keyBuffer, sizeof(keyBuffer), "%u", i);
|
|
445
|
+
xt_value temporary = xt_string_from_cstr("");
|
|
446
|
+
int wrote = xt_json_replacer_write(ctx, value, xt_string_from_cstr(keyBuffer), depth + 1,
|
|
447
|
+
&temporary);
|
|
448
|
+
*out = xt_add(*out, wrote ? temporary : xt_string_from_cstr("null"));
|
|
449
|
+
}
|
|
450
|
+
xt_json_replacer_indent(ctx, depth, out);
|
|
451
|
+
xt_json_replacer_leave(ctx);
|
|
452
|
+
*out = xt_add(*out, xt_string_from_cstr("]"));
|
|
453
|
+
return 1;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
xt_value keys = xt_object_keys(value);
|
|
457
|
+
xt_array *list = xt_as_array(keys);
|
|
458
|
+
*out = xt_add(*out, xt_string_from_cstr("{"));
|
|
459
|
+
int written = 0;
|
|
460
|
+
if (list) {
|
|
461
|
+
for (uint32_t i = 0; i < list->length; i++) {
|
|
462
|
+
xt_value childKey = list->items[i];
|
|
463
|
+
if (!xt_json_replacer_allows(ctx->replacer, childKey)) continue;
|
|
464
|
+
xt_value temporary = xt_string_from_cstr("");
|
|
465
|
+
int wrote = xt_json_replacer_write(ctx, value, childKey, depth + 1, &temporary);
|
|
466
|
+
if (!wrote) continue;
|
|
467
|
+
if (written > 0) *out = xt_add(*out, xt_string_from_cstr(","));
|
|
468
|
+
written++;
|
|
469
|
+
xt_json_replacer_indent(ctx, depth + 1, out);
|
|
470
|
+
*out = xt_add(*out, xt_string_from_cstr("\""));
|
|
471
|
+
*out = xt_add(*out, childKey);
|
|
472
|
+
*out = xt_add(*out, xt_string_from_cstr("\":"));
|
|
473
|
+
if (xt_json_indented(ctx->indent)) *out = xt_add(*out, xt_string_from_cstr(" "));
|
|
474
|
+
*out = xt_add(*out, temporary);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
xt_json_replacer_indent(ctx, depth, out);
|
|
478
|
+
xt_json_replacer_leave(ctx);
|
|
479
|
+
*out = xt_add(*out, xt_string_from_cstr("}"));
|
|
480
|
+
return 1;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
static int xt_json_replacer_write(xt_json_replacer_context *ctx, xt_value holder, xt_value key,
|
|
484
|
+
int depth, xt_value *out) {
|
|
485
|
+
xt_value value = xt_get(holder, key);
|
|
486
|
+
if (XT_IS_FUNCTION(ctx->replacer)) {
|
|
487
|
+
xt_value args[2] = {key, value};
|
|
488
|
+
value = xt_call_with_this(ctx->replacer, holder, 2, args);
|
|
489
|
+
}
|
|
490
|
+
if (xt_is_date(value)) {
|
|
491
|
+
value = xt_call_method(value, xt_string_from_cstr("toJSON"), 1, &key);
|
|
492
|
+
} else if (XT_IS_ARRAY(value) ||
|
|
493
|
+
(XT_IS_OBJECT(value) &&
|
|
494
|
+
(((xt_object *)XT_GET_PTR(value))->header.kind == XT_OBJECT_KIND_OBJECT ||
|
|
495
|
+
((xt_object *)XT_GET_PTR(value))->header.kind == XT_OBJECT_KIND_ERROR))) {
|
|
496
|
+
xt_value toJSON = XT_IS_ARRAY(value) ? xt_get(value, xt_string_from_cstr("toJSON"))
|
|
497
|
+
: xt_object_get(value, xt_string_from_cstr("toJSON"));
|
|
498
|
+
if (XT_IS_FUNCTION(toJSON)) {
|
|
499
|
+
xt_value args[1] = {key};
|
|
500
|
+
value = xt_call_with_this(toJSON, value, 1, args);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
if (value == XT_UNDEFINED || XT_IS_FUNCTION(value) || xt_is_symbol(value)) return 0;
|
|
504
|
+
if (XT_IS_BIGINT(value)) {
|
|
505
|
+
xt_value message = xt_string_from_cstr("Do not know how to serialize a BigInt");
|
|
506
|
+
xt_throw(xt_type_error_ctor(1, &message));
|
|
507
|
+
}
|
|
508
|
+
if (XT_IS_ARRAY(value)) return xt_json_replacer_container(ctx, value, depth, out);
|
|
509
|
+
if (XT_IS_OBJECT(value)) {
|
|
510
|
+
int kind = ((xt_object *)XT_GET_PTR(value))->header.kind;
|
|
511
|
+
if (kind == XT_OBJECT_KIND_MAP || kind == XT_OBJECT_KIND_SET ||
|
|
512
|
+
kind == XT_OBJECT_KIND_REGEXP || kind == XT_OBJECT_KIND_PROMISE ||
|
|
513
|
+
kind == XT_OBJECT_KIND_GENERATOR || kind == XT_OBJECT_KIND_ITERATOR ||
|
|
514
|
+
kind == XT_OBJECT_KIND_ASYNC) {
|
|
515
|
+
*out = xt_add(*out, xt_string_from_cstr("{}"));
|
|
516
|
+
return 1;
|
|
517
|
+
}
|
|
518
|
+
return xt_json_replacer_container(ctx, value, depth, out);
|
|
519
|
+
}
|
|
520
|
+
xt_json_stringify_value(value, ctx->indent, depth, out);
|
|
521
|
+
return 1;
|
|
522
|
+
}
|
|
523
|
+
|
|
215
524
|
xt_value xt_json_stringify(int32_t argc, xt_value *argv) {
|
|
216
|
-
int indent = 0;
|
|
217
|
-
xt_value space = xt_arg_at(argc, argv, 1);
|
|
218
|
-
if (XT_IS_NUMBER(space)) indent = xt_to_int32(space);
|
|
219
|
-
else if (XT_IS_STRING(space)) indent = (int)((xt_string *)XT_GET_PTR(space))->length;
|
|
220
|
-
if (indent < 0) indent = 0;
|
|
221
|
-
if (indent > 10) indent = 10;
|
|
222
525
|
xt_value value = xt_arg_at(argc, argv, 0);
|
|
223
526
|
if (value == XT_UNDEFINED || XT_IS_FUNCTION(value) || xt_is_symbol(value)) return XT_UNDEFINED;
|
|
527
|
+
/* Signature: stringify(value, replacer, space). The replacer is argv[1] and
|
|
528
|
+
* the indentation is argv[2]; reading argv[1] as `space` silently ignored
|
|
529
|
+
* `JSON.stringify(value, null, 2)`. */
|
|
530
|
+
xt_value indent = xt_json_space_unit(xt_arg_at(argc, argv, 2));
|
|
531
|
+
xt_value replacer = xt_arg_at(argc, argv, 1);
|
|
532
|
+
if (XT_IS_FUNCTION(replacer) || XT_IS_ARRAY(replacer)) {
|
|
533
|
+
xt_json_replacer_context context = {replacer, indent, NULL, 0, 0};
|
|
534
|
+
xt_value wrapper = xt_object_new();
|
|
535
|
+
xt_object_set(wrapper, xt_string_from_cstr(""), value);
|
|
536
|
+
xt_value out = xt_string_from_cstr("");
|
|
537
|
+
int wrote = xt_json_replacer_write(&context, wrapper, xt_string_from_cstr(""), 0, &out);
|
|
538
|
+
free(context.path);
|
|
539
|
+
return wrote ? out : XT_UNDEFINED;
|
|
540
|
+
}
|
|
541
|
+
/* A caught circular-structure error longjmps past xt_json_leave; start every
|
|
542
|
+
* top-level serialization with a clean path. */
|
|
543
|
+
xt_json_path_count = 0;
|
|
224
544
|
xt_value out = xt_string_from_cstr("");
|
|
225
545
|
xt_json_stringify_value(value, indent, 0, &out);
|
|
226
546
|
return out;
|
|
@@ -41,24 +41,33 @@ xt_value xt_number_static(xt_value name, int32_t argc, xt_value *argv) {
|
|
|
41
41
|
xt_value xt_string_static(xt_value name, int32_t argc, xt_value *argv) {
|
|
42
42
|
const char *fn = xt_string_data(name);
|
|
43
43
|
if (!fn) return XT_UNDEFINED;
|
|
44
|
-
if (strcmp(fn, "fromCharCode") == 0
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
if (strcmp(fn, "fromCharCode") == 0) {
|
|
45
|
+
/* `fromCharCode` takes UTF-16 code units (modulo 65536) and joins adjacent
|
|
46
|
+
* high/low surrogates into one code point, like JavaScript. */
|
|
47
|
+
if (argc <= 0) return xt_string_from_cstr("");
|
|
48
|
+
uint16_t *units = (uint16_t *)malloc(sizeof(uint16_t) * (size_t)argc);
|
|
49
|
+
if (!units) abort();
|
|
50
|
+
for (int32_t i = 0; i < argc; i++) units[i] = (uint16_t)(xt_to_int32(argv[i]) & 0xFFFF);
|
|
51
|
+
xt_value result = xt_string_from_units(units, (size_t)argc);
|
|
52
|
+
free(units);
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
if (strcmp(fn, "fromCodePoint") == 0) {
|
|
56
|
+
char *out = (char *)malloc((size_t)argc * 4 + 1);
|
|
57
|
+
if (!out) abort();
|
|
47
58
|
size_t length = 0;
|
|
48
59
|
for (int32_t i = 0; i < argc; i++) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
memcpy(mutable + length, buffer, (size_t)bytes);
|
|
57
|
-
length += (size_t)bytes;
|
|
60
|
+
int32_t code = xt_to_int32(argv[i]);
|
|
61
|
+
if (code < 0 || code > 0x10FFFF) {
|
|
62
|
+
free(out);
|
|
63
|
+
xt_throw(xt_error_from_message("RangeError: Invalid code point"));
|
|
64
|
+
return XT_UNDEFINED;
|
|
65
|
+
}
|
|
66
|
+
length += xt_utf8_encode((uint32_t)code, out + length);
|
|
58
67
|
}
|
|
59
|
-
|
|
60
|
-
out
|
|
61
|
-
return
|
|
68
|
+
xt_value result = xt_string_new(out, length);
|
|
69
|
+
free(out);
|
|
70
|
+
return result;
|
|
62
71
|
}
|
|
63
72
|
if (strcmp(fn, "raw") == 0) {
|
|
64
73
|
xt_value strings = xt_arg_at(argc, argv, 0);
|