xbintsc 0.5.6 → 0.5.21
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 +20 -10
- package/README.md +8 -7
- package/README.zh-CN.md +6 -6
- 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 +11 -2
- package/dist/src/codegen/generator/calls/access.js.map +1 -1
- package/dist/src/codegen/generator/calls/closures.js +12 -4
- package/dist/src/codegen/generator/calls/closures.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 +5 -0
- package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
- package/dist/src/codegen/generator/module.js +0 -7
- 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 +23 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/statements/control-flow.js +1 -4
- 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.js +26 -1
- 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 +95 -234
- 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 +112 -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/extensions/node/fs/index.d.ts +4 -3
- package/dist/src/extensions/node/fs/index.js +12 -3
- package/dist/src/extensions/node/fs/index.js.map +1 -1
- package/dist/src/extensions/node/fs-promises/index.d.ts +5 -5
- package/dist/src/extensions/node/fs-promises/index.js +15 -6
- package/dist/src/extensions/node/fs-promises/index.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/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.js +1 -1
- package/dist/tests/e2e/async-fs.test.d.ts +9 -0
- package/dist/tests/e2e/async-fs.test.js +119 -0
- package/dist/tests/e2e/async-fs.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/fetch.test.js +24 -0
- package/dist/tests/e2e/fetch.test.js.map +1 -1
- 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-inline-svg.test.d.ts +11 -0
- package/dist/tests/e2e/gui-inline-svg.test.js +160 -0
- package/dist/tests/e2e/gui-inline-svg.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-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/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 +20 -16
- package/doc/ai/extensions.md +13 -10
- package/doc/ai/language-support.md +19 -14
- package/doc/ai/troubleshooting.md +11 -9
- 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 +16 -15
- package/doc/ai/zh-CN/extensions.md +12 -9
- package/doc/ai/zh-CN/language-support.md +19 -15
- package/doc/ai/zh-CN/troubleshooting.md +9 -8
- package/doc/gui/api.md +8 -0
- package/doc/gui/build.md +13 -4
- package/doc/gui/known-issues.md +19 -14
- package/doc/gui/media.md +32 -3
- package/doc/gui/rendering.md +3 -1
- package/doc/gui.md +28 -5
- package/doc/icon.md +5 -4
- package/doc/implemented/async.md +51 -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 +44 -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 +49 -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 -355
- 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 +20 -0
- package/doc/unimplemented/node/bun.md +9 -0
- package/doc/unimplemented/node/fs-promises.md +20 -0
- package/doc/unimplemented/node/fs.md +30 -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 -275
- package/doc/xbintsc.config.schema.json +12 -0
- package/doc/zh-CN/gui/api.md +7 -0
- package/doc/zh-CN/gui/build.md +11 -3
- package/doc/zh-CN/gui/known-issues.md +17 -11
- package/doc/zh-CN/gui/media.md +26 -2
- package/doc/zh-CN/gui/rendering.md +2 -1
- package/doc/zh-CN/gui.md +21 -3
- package/doc/zh-CN/icon.md +5 -4
- package/doc/zh-CN/implemented/async.md +49 -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 +31 -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 +30 -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 -350
- 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 +20 -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 -237
- package/llms.txt +32 -4
- package/package.json +1 -1
- package/runtime/ext_gui/inline_svg.cpp +219 -0
- package/runtime/ext_gui/inline_svg.h +41 -0
- package/runtime/ext_gui/layout.cpp +18 -0
- package/runtime/ext_gui/layout.h +7 -0
- package/runtime/ext_gui/layout_flow.cpp +4 -3
- package/runtime/ext_gui/paint.cpp +14 -0
- package/runtime/ext_gui/paint.h +5 -1
- package/runtime/ext_gui/renderer_image.cpp +53 -25
- package/runtime/ext_gui/renderer_shaders.h +2 -2
- package/runtime/ext_gui/stb_image.h +1 -17
- package/runtime/ext_gui/style_ua.cpp +3 -0
- package/runtime/ext_gui/svg.cpp +122 -39
- package/runtime/ext_gui/svg.h +14 -3
- package/runtime/ext_gui/window.cpp +28 -0
- package/runtime/ext_node/child_process/child_process.c +173 -73
- package/runtime/ext_node/fs/async_api.c +314 -0
- package/runtime/ext_node/fs/async_complete.c +99 -0
- package/runtime/ext_node/fs/async_fh.c +206 -0
- package/runtime/ext_node/fs/async_job.c +81 -0
- package/runtime/ext_node/fs/async_job.h +132 -0
- package/runtime/ext_node/fs/async_worker.c +534 -0
- package/runtime/ext_node/fs/async_worker_dir.c +439 -0
- package/runtime/ext_node/fs/async_worker_dir.h +33 -0
- package/runtime/ext_node/fs/async_worker_fd.c +74 -0
- package/runtime/ext_node/fs/dir.c +60 -15
- package/runtime/ext_node/fs/fs_common.h +9 -0
- package/runtime/ext_node/fs/fs_ops.c +18 -29
- package/runtime/ext_node/fs/parts/builtins.inc +34 -0
- package/runtime/ext_node/fs/parts/platform.inc +66 -0
- package/runtime/ext_node/fs/promises.c +44 -234
- package/runtime/rt.h +15 -0
- package/runtime/rt_internal.h +108 -0
- package/runtime/xt_alloc.c +43 -7
- package/runtime/xt_array_buffer.c +284 -0
- package/runtime/xt_async.c +46 -21
- package/runtime/xt_async_io.c +333 -0
- package/runtime/xt_async_io.h +47 -0
- package/runtime/xt_bigint/helpers.inc +3 -3
- package/runtime/xt_builtins.c +21 -17
- package/runtime/xt_constructors.c +12 -2
- package/runtime/xt_containers/access.inc +148 -3
- package/runtime/xt_containers/objects.inc +26 -2
- package/runtime/xt_containers/shapes.inc +71 -0
- package/runtime/xt_containers.c +1 -0
- package/runtime/xt_coroutine.c +17 -0
- package/runtime/xt_fetch/async.inc +295 -0
- package/runtime/xt_fetch/request.inc +6 -183
- package/runtime/xt_fetch/socket.inc +5 -4
- package/runtime/xt_fetch.c +6 -4
- package/runtime/xt_generator.c +299 -10
- package/runtime/xt_io/inspect.inc +112 -0
- package/runtime/xt_loop.c +79 -7
- package/runtime/xt_performance.c +37 -0
- package/runtime/xt_promise.c +63 -1
- package/runtime/xt_stdlib/arrays.inc +1 -1
- package/runtime/xt_stdlib/dispatch.inc +46 -11
- package/runtime/xt_stdlib/strings.inc +1 -1
- package/runtime/xt_stdlib2/array-statics.inc +25 -0
- 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 +24 -0
- package/runtime/xt_stdlib2/json.inc +310 -19
- package/runtime/xt_stdlib2/number-string-statics.inc +1 -1
- package/runtime/xt_stdlib2/objects.inc +122 -0
- package/runtime/xt_stdlib2/set.inc +1 -1
- 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 +35 -5
- package/runtime/xt_typed_array/elements.inc +159 -0
- package/runtime/xt_typed_array/methods.inc +21 -5
- package/runtime/xt_typed_array.c +7 -10
- package/runtime/xt_url.c +375 -0
- package/runtime/xt_values/arithmetic.inc +2 -2
- package/runtime/xt_values/conversions.inc +1 -1
- 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 +10 -2
- package/src/codegen/generator/calls/closures.ts +12 -4
- package/src/codegen/generator/context.ts +23 -3
- package/src/codegen/generator/expressions/operators.ts +27 -13
- package/src/codegen/generator/expressions/primary.ts +4 -0
- package/src/codegen/generator/module.ts +0 -7
- package/src/codegen/generator/numeric.ts +85 -11
- package/src/codegen/generator/state.ts +23 -0
- package/src/codegen/generator/statements/control-flow.ts +1 -4
- package/src/codegen/generator/statements/loops.ts +50 -16
- package/src/codegen/generator/tables.ts +26 -1
- 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 +94 -328
- 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 +134 -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/extensions/node/fs/index.ts +12 -3
- package/src/extensions/node/fs-promises/index.ts +15 -6
- 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
|
@@ -4,11 +4,111 @@ int xt_is_date(xt_value value) {
|
|
|
4
4
|
return XT_IS_OBJECT(value) && ((xt_object *)XT_GET_PTR(value))->header.kind == XT_OBJECT_KIND_DATE;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
/* Parse `YYYY-MM-DD`, optionally followed by `T`/space and
|
|
8
|
+
* `HH:MM[:SS[.mmm]]`, then `Z`, `+HH:MM`/`-HH:MM` (or the HHMM spelling).
|
|
9
|
+
* A date-only value is UTC; a date-time without an offset is local time, which
|
|
10
|
+
* is what ECMAScript specifies. Returns milliseconds since the epoch, or NaN
|
|
11
|
+
* for anything outside this subset. */
|
|
12
|
+
static int xt_date_digits(const char *text, int count, int *out) {
|
|
13
|
+
int value = 0;
|
|
14
|
+
for (int i = 0; i < count; i++) {
|
|
15
|
+
if (text[i] < '0' || text[i] > '9') return 0;
|
|
16
|
+
value = value * 10 + (text[i] - '0');
|
|
17
|
+
}
|
|
18
|
+
*out = value;
|
|
19
|
+
return 1;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static double xt_date_parse_text(const char *text) {
|
|
23
|
+
size_t length = strlen(text);
|
|
24
|
+
size_t i = 0;
|
|
25
|
+
int year = 0, month = 0, day = 0;
|
|
26
|
+
if (length < 10 || !xt_date_digits(text, 4, &year) || text[4] != '-' ||
|
|
27
|
+
!xt_date_digits(text + 5, 2, &month) || text[7] != '-' ||
|
|
28
|
+
!xt_date_digits(text + 8, 2, &day)) {
|
|
29
|
+
return NAN;
|
|
30
|
+
}
|
|
31
|
+
i = 10;
|
|
32
|
+
int hour = 0, minute = 0, second = 0, millis = 0;
|
|
33
|
+
int hasTime = 0;
|
|
34
|
+
if (i < length && (text[i] == 'T' || text[i] == ' ')) {
|
|
35
|
+
hasTime = 1;
|
|
36
|
+
i++;
|
|
37
|
+
if (i + 5 > length || !xt_date_digits(text + i, 2, &hour) || text[i + 2] != ':' ||
|
|
38
|
+
!xt_date_digits(text + i + 3, 2, &minute)) {
|
|
39
|
+
return NAN;
|
|
40
|
+
}
|
|
41
|
+
i += 5;
|
|
42
|
+
if (i + 3 <= length && text[i] == ':') {
|
|
43
|
+
if (!xt_date_digits(text + i + 1, 2, &second)) return NAN;
|
|
44
|
+
i += 3;
|
|
45
|
+
}
|
|
46
|
+
if (i + 4 <= length && text[i] == '.') {
|
|
47
|
+
if (!xt_date_digits(text + i + 1, 3, &millis)) return NAN;
|
|
48
|
+
i += 4;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
int utc = !hasTime;
|
|
52
|
+
int offsetSeconds = 0;
|
|
53
|
+
if (i < length) {
|
|
54
|
+
if (text[i] == 'Z') {
|
|
55
|
+
utc = 1;
|
|
56
|
+
i++;
|
|
57
|
+
} else if (text[i] == '+' || text[i] == '-') {
|
|
58
|
+
int sign = text[i] == '-' ? -1 : 1;
|
|
59
|
+
i++;
|
|
60
|
+
int offsetHour = 0, offsetMinute = 0;
|
|
61
|
+
if (i + 5 <= length && xt_date_digits(text + i, 2, &offsetHour) && text[i + 2] == ':' &&
|
|
62
|
+
xt_date_digits(text + i + 3, 2, &offsetMinute)) {
|
|
63
|
+
i += 5;
|
|
64
|
+
} else if (i + 4 <= length && xt_date_digits(text + i, 2, &offsetHour) &&
|
|
65
|
+
xt_date_digits(text + i + 2, 2, &offsetMinute)) {
|
|
66
|
+
i += 4;
|
|
67
|
+
} else {
|
|
68
|
+
return NAN;
|
|
69
|
+
}
|
|
70
|
+
if (offsetHour > 23 || offsetMinute > 59) return NAN;
|
|
71
|
+
offsetSeconds = sign * (offsetHour * 3600 + offsetMinute * 60);
|
|
72
|
+
utc = 1;
|
|
73
|
+
} else {
|
|
74
|
+
return NAN;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (i != length) return NAN;
|
|
78
|
+
if (month < 1 || month > 12 || day < 1 || day > 31 ||
|
|
79
|
+
hour > 23 || minute > 59 || second > 59) {
|
|
80
|
+
return NAN;
|
|
81
|
+
}
|
|
82
|
+
struct tm tm;
|
|
83
|
+
memset(&tm, 0, sizeof(tm));
|
|
84
|
+
tm.tm_year = year - 1900;
|
|
85
|
+
tm.tm_mon = month - 1;
|
|
86
|
+
tm.tm_mday = day;
|
|
87
|
+
tm.tm_hour = hour;
|
|
88
|
+
tm.tm_min = minute;
|
|
89
|
+
tm.tm_sec = second;
|
|
90
|
+
time_t seconds;
|
|
91
|
+
if (utc) {
|
|
92
|
+
seconds = xt_timegm(&tm);
|
|
93
|
+
} else {
|
|
94
|
+
tm.tm_isdst = -1;
|
|
95
|
+
seconds = mktime(&tm);
|
|
96
|
+
if (seconds == (time_t)-1) return NAN;
|
|
97
|
+
}
|
|
98
|
+
if (utc && offsetSeconds != 0) seconds -= offsetSeconds;
|
|
99
|
+
return (double)seconds * 1000.0 + (double)millis;
|
|
100
|
+
}
|
|
101
|
+
|
|
7
102
|
xt_value xt_date_ctor(int32_t argc, xt_value *argv) {
|
|
8
103
|
xt_date *date = (xt_date *)xt_alloc(sizeof(xt_date), XT_OBJECT_KIND_DATE);
|
|
9
104
|
if (argc == 0) date->time = (double)time(NULL) * 1000.0;
|
|
10
|
-
else if (argc == 1)
|
|
11
|
-
|
|
105
|
+
else if (argc == 1) {
|
|
106
|
+
if (XT_IS_STRING(argv[0])) {
|
|
107
|
+
date->time = xt_date_parse_text(xt_string_data(argv[0]));
|
|
108
|
+
} else {
|
|
109
|
+
date->time = xt_to_number(argv[0]);
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
12
112
|
struct tm tm;
|
|
13
113
|
memset(&tm, 0, sizeof(tm));
|
|
14
114
|
tm.tm_year = xt_to_int32(argv[0]) - 1900;
|
|
@@ -27,7 +127,11 @@ xt_value xt_date_static(xt_value name, int32_t argc, xt_value *argv) {
|
|
|
27
127
|
const char *fn = xt_string_data(name);
|
|
28
128
|
if (!fn) return XT_UNDEFINED;
|
|
29
129
|
if (strcmp(fn, "now") == 0) return xt_number((double)time(NULL) * 1000.0);
|
|
30
|
-
if (strcmp(fn, "parse") == 0)
|
|
130
|
+
if (strcmp(fn, "parse") == 0) {
|
|
131
|
+
xt_value input = xt_arg_at(argc, argv, 0);
|
|
132
|
+
if (!XT_IS_STRING(input)) return xt_number(NAN);
|
|
133
|
+
return xt_number(xt_date_parse_text(xt_string_data(input)));
|
|
134
|
+
}
|
|
31
135
|
if (strcmp(fn, "UTC") == 0) {
|
|
32
136
|
struct tm tm;
|
|
33
137
|
memset(&tm, 0, sizeof(tm));
|
|
@@ -68,6 +172,10 @@ static xt_value xt_date_method(xt_value target, const char *method, int32_t argc
|
|
|
68
172
|
if (strcmp(name, "getSeconds") == 0) return xt_number(tm.tm_sec);
|
|
69
173
|
if (strcmp(name, "getMilliseconds") == 0) return xt_number(fmod(date->time, 1000.0));
|
|
70
174
|
if (strcmp(method, "toISOString") == 0) {
|
|
175
|
+
if (isnan(date->time)) {
|
|
176
|
+
xt_value message = xt_string_from_cstr("Invalid time value");
|
|
177
|
+
xt_throw(xt_range_error_ctor(1, &message));
|
|
178
|
+
}
|
|
71
179
|
char buffer[64];
|
|
72
180
|
snprintf(buffer, sizeof(buffer), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", tm.tm_year + 1900, tm.tm_mon + 1,
|
|
73
181
|
tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, (int)fmod(date->time, 1000.0));
|
|
@@ -112,6 +112,30 @@ xt_value xt_error_constructor(xt_value nameValue) {
|
|
|
112
112
|
return closure;
|
|
113
113
|
}
|
|
114
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
|
+
|
|
115
139
|
xt_value xt_error_to_string(xt_value error) {
|
|
116
140
|
xt_value name = xt_object_get(error, xt_string_from_cstr("name"));
|
|
117
141
|
xt_value message = xt_object_get(error, xt_string_from_cstr("message"));
|
|
@@ -133,50 +133,152 @@ static xt_value xt_json_parse_value(xt_json_cursor *c) {
|
|
|
133
133
|
return xt_json_parse_number(c);
|
|
134
134
|
}
|
|
135
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
|
+
|
|
136
168
|
xt_value xt_json_parse(int32_t argc, xt_value *argv) {
|
|
137
169
|
xt_value input = xt_to_string(xt_arg_at(argc, argv, 0));
|
|
138
170
|
xt_string *s = xt_as_string(input);
|
|
139
171
|
if (!s) return XT_UNDEFINED;
|
|
140
172
|
xt_json_cursor cursor = {xt_string_bytes(s), s->length, 0};
|
|
141
|
-
|
|
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);
|
|
142
179
|
}
|
|
143
180
|
|
|
144
|
-
static void xt_json_stringify_value(xt_value value,
|
|
181
|
+
static void xt_json_stringify_value(xt_value value, xt_value indent, int depth, xt_value *out);
|
|
145
182
|
|
|
146
|
-
|
|
147
|
-
|
|
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("");
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
static int xt_json_indented(xt_value unit) {
|
|
214
|
+
return XT_IS_STRING(unit) && xt_as_string(unit)->length > 0;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
static void xt_json_indent(xt_value *out, xt_value unit, int depth) {
|
|
218
|
+
if (!xt_json_indented(unit)) return;
|
|
148
219
|
*out = xt_add(*out, xt_string_from_cstr("\n"));
|
|
149
|
-
for (int i = 0; i <
|
|
220
|
+
for (int i = 0; i < depth; i++) *out = xt_add(*out, unit);
|
|
221
|
+
}
|
|
222
|
+
|
|
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--;
|
|
150
249
|
}
|
|
151
250
|
|
|
152
|
-
static void xt_json_stringify_array(xt_value value,
|
|
251
|
+
static void xt_json_stringify_array(xt_value value, xt_value indent, int depth, xt_value *out) {
|
|
153
252
|
xt_array *array = xt_as_array(value);
|
|
154
253
|
if (!array || array->length == 0) { *out = xt_add(*out, xt_string_from_cstr("[]")); return; }
|
|
155
254
|
*out = xt_add(*out, xt_string_from_cstr("["));
|
|
255
|
+
xt_json_enter(value);
|
|
156
256
|
for (uint32_t i = 0; i < array->length; i++) {
|
|
157
257
|
if (i > 0) *out = xt_add(*out, xt_string_from_cstr(","));
|
|
158
258
|
xt_json_indent(out, indent, depth + 1);
|
|
159
259
|
xt_json_stringify_value(array->items[i], indent, depth + 1, out);
|
|
160
260
|
}
|
|
161
261
|
xt_json_indent(out, indent, depth);
|
|
262
|
+
xt_json_leave();
|
|
162
263
|
*out = xt_add(*out, xt_string_from_cstr("]"));
|
|
163
264
|
}
|
|
164
265
|
|
|
165
|
-
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) {
|
|
166
267
|
xt_value keys = xt_object_keys(value);
|
|
167
268
|
xt_array *array = xt_as_array(keys);
|
|
168
269
|
if (!array) { *out = xt_add(*out, xt_string_from_cstr("{}")); return; }
|
|
169
270
|
int any = 0;
|
|
170
271
|
for (uint32_t i = 0; i < array->length; i++) {
|
|
171
|
-
xt_value item =
|
|
272
|
+
xt_value item = xt_get(value, array->items[i]);
|
|
172
273
|
if (item != XT_UNDEFINED && !XT_IS_FUNCTION(item) && !xt_is_symbol(item)) { any = 1; break; }
|
|
173
274
|
}
|
|
174
275
|
if (!any) { *out = xt_add(*out, xt_string_from_cstr("{}")); return; }
|
|
175
276
|
*out = xt_add(*out, xt_string_from_cstr("{"));
|
|
277
|
+
xt_json_enter(value);
|
|
176
278
|
int written = 0;
|
|
177
279
|
for (uint32_t i = 0; i < array->length; i++) {
|
|
178
280
|
xt_value key = array->items[i];
|
|
179
|
-
xt_value item =
|
|
281
|
+
xt_value item = xt_get(value, key);
|
|
180
282
|
/* `undefined`, functions and symbols are omitted from objects. */
|
|
181
283
|
if (item == XT_UNDEFINED || XT_IS_FUNCTION(item) || xt_is_symbol(item)) continue;
|
|
182
284
|
if (written > 0) *out = xt_add(*out, xt_string_from_cstr(","));
|
|
@@ -185,20 +287,21 @@ static void xt_json_stringify_object(xt_value value, int indent, int depth, xt_v
|
|
|
185
287
|
*out = xt_add(*out, xt_string_from_cstr("\""));
|
|
186
288
|
*out = xt_add(*out, key);
|
|
187
289
|
*out = xt_add(*out, xt_string_from_cstr("\":"));
|
|
188
|
-
if (indent
|
|
290
|
+
if (xt_json_indented(indent)) *out = xt_add(*out, xt_string_from_cstr(" "));
|
|
189
291
|
xt_json_stringify_value(item, indent, depth + 1, out);
|
|
190
292
|
}
|
|
191
293
|
xt_json_indent(out, indent, depth);
|
|
294
|
+
xt_json_leave();
|
|
192
295
|
*out = xt_add(*out, xt_string_from_cstr("}"));
|
|
193
296
|
}
|
|
194
297
|
|
|
195
|
-
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) {
|
|
196
299
|
if (value == XT_UNDEFINED || value == XT_NULL || XT_IS_FUNCTION(value) || xt_is_symbol(value)) {
|
|
197
300
|
*out = xt_add(*out, xt_string_from_cstr("null"));
|
|
198
301
|
return;
|
|
199
302
|
}
|
|
200
303
|
if (XT_IS_BIGINT(value)) {
|
|
201
|
-
xt_throw(
|
|
304
|
+
xt_throw(xt_error_from_message("TypeError: Do not know how to serialize a BigInt"));
|
|
202
305
|
return;
|
|
203
306
|
}
|
|
204
307
|
if (XT_IS_BOOL(value)) { *out = xt_add(*out, value == XT_TRUE ? xt_string_from_cstr("true") : xt_string_from_cstr("false")); return; }
|
|
@@ -237,19 +340,207 @@ static void xt_json_stringify_value(xt_value value, int indent, int depth, xt_va
|
|
|
237
340
|
return;
|
|
238
341
|
}
|
|
239
342
|
if (XT_IS_ARRAY(value)) { xt_json_stringify_array(value, indent, depth, out); return; }
|
|
240
|
-
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
|
+
}
|
|
241
375
|
*out = xt_add(*out, xt_string_from_cstr("null"));
|
|
242
376
|
}
|
|
243
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
|
+
|
|
244
524
|
xt_value xt_json_stringify(int32_t argc, xt_value *argv) {
|
|
245
|
-
int indent = 0;
|
|
246
|
-
xt_value space = xt_arg_at(argc, argv, 1);
|
|
247
|
-
if (XT_IS_NUMBER(space)) indent = xt_to_int32(space);
|
|
248
|
-
else if (XT_IS_STRING(space)) indent = (int)xt_string_utf16_length((xt_string *)XT_GET_PTR(space));
|
|
249
|
-
if (indent < 0) indent = 0;
|
|
250
|
-
if (indent > 10) indent = 10;
|
|
251
525
|
xt_value value = xt_arg_at(argc, argv, 0);
|
|
252
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;
|
|
253
544
|
xt_value out = xt_string_from_cstr("");
|
|
254
545
|
xt_json_stringify_value(value, indent, 0, &out);
|
|
255
546
|
return out;
|
|
@@ -60,7 +60,7 @@ xt_value xt_string_static(xt_value name, int32_t argc, xt_value *argv) {
|
|
|
60
60
|
int32_t code = xt_to_int32(argv[i]);
|
|
61
61
|
if (code < 0 || code > 0x10FFFF) {
|
|
62
62
|
free(out);
|
|
63
|
-
xt_throw(
|
|
63
|
+
xt_throw(xt_error_from_message("RangeError: Invalid code point"));
|
|
64
64
|
return XT_UNDEFINED;
|
|
65
65
|
}
|
|
66
66
|
length += xt_utf8_encode((uint32_t)code, out + length);
|