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
package/runtime/xt_generator.c
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* xbintsc runtime — stackful generators.
|
|
2
|
+
* xbintsc runtime — stackful generators and async generators.
|
|
3
3
|
*
|
|
4
4
|
* A generator function object carries `is_generator`. Calling it does not run
|
|
5
5
|
* the body; it creates an `xt_generator` that owns a private stack. `.next()`
|
|
@@ -8,27 +8,30 @@
|
|
|
8
8
|
* `finally` and nested loops work across suspension points without a state
|
|
9
9
|
* machine transform.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* An `async function*` uses the same coroutine, but every `.next()` /
|
|
12
|
+
* `.throw()` / `.return()` returns a promise. The body may also suspend at an
|
|
13
|
+
* `await`: `xt_generator_await` parks the coroutine on the awaited promise and
|
|
14
|
+
* leaves the current `.next()` promise pending until the body yields or
|
|
15
|
+
* completes. This is what makes `for await...of` work without a state machine.
|
|
16
|
+
*
|
|
17
|
+
* The private stack and the context switch come from `xt_coroutine.c`, which
|
|
18
|
+
* `async` functions use as well. The generator's exception stack is swapped
|
|
19
|
+
* alongside it so a `throw` inside the body still targets the body's own
|
|
20
|
+
* `try` frames.
|
|
14
21
|
*/
|
|
15
22
|
|
|
16
|
-
#define _XOPEN_SOURCE 700
|
|
17
|
-
|
|
18
23
|
#include "rt_internal.h"
|
|
19
24
|
|
|
20
25
|
#include <stdlib.h>
|
|
21
26
|
#include <string.h>
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
#include <ucontext.h>
|
|
31
|
-
#endif
|
|
28
|
+
/* One queued async-generator request. Requests are processed in call order, so
|
|
29
|
+
* two `.next()` calls before the body yields do not overwrite each other. */
|
|
30
|
+
typedef struct {
|
|
31
|
+
xt_value promise;
|
|
32
|
+
xt_value sent;
|
|
33
|
+
int kind; /* 0 = next, 1 = throw, 2 = return */
|
|
34
|
+
} xt_async_request;
|
|
32
35
|
|
|
33
36
|
typedef struct xt_generator {
|
|
34
37
|
xt_header header;
|
|
@@ -44,41 +47,43 @@ typedef struct xt_generator {
|
|
|
44
47
|
int started;
|
|
45
48
|
int done;
|
|
46
49
|
int threw;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
int
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
* collector before switching away. */
|
|
60
|
-
jmp_buf caller_regs;
|
|
61
|
-
int has_caller_regs;
|
|
62
|
-
#else
|
|
63
|
-
ucontext_t ctx;
|
|
64
|
-
ucontext_t caller;
|
|
65
|
-
#endif
|
|
50
|
+
/* Async-generator state. `pending_promise` belongs to the request currently
|
|
51
|
+
* executing; `requests` holds calls made while it is pending. */
|
|
52
|
+
int is_async;
|
|
53
|
+
xt_value pending_promise;
|
|
54
|
+
xt_value resume_value;
|
|
55
|
+
int await_threw;
|
|
56
|
+
xt_async_request *requests;
|
|
57
|
+
uint32_t request_count;
|
|
58
|
+
uint32_t request_capacity;
|
|
59
|
+
/* Private stack, context switch and GC region bookkeeping live in
|
|
60
|
+
* xt_coroutine.c; `NULL` once the body has finished. */
|
|
61
|
+
xt_coroutine *coroutine;
|
|
66
62
|
} xt_generator;
|
|
67
63
|
|
|
64
|
+
/* Resolved async iterator for a *synchronous* iterable (`for await` over an
|
|
65
|
+
* array). The source uses the ordinary index protocol; each step is wrapped in
|
|
66
|
+
* an already-settled promise. */
|
|
67
|
+
typedef struct {
|
|
68
|
+
xt_header header;
|
|
69
|
+
xt_value iterator;
|
|
70
|
+
xt_value index;
|
|
71
|
+
int done;
|
|
72
|
+
} xt_async_iterator_state;
|
|
73
|
+
|
|
68
74
|
/* The generator whose coroutine is running, if any. */
|
|
69
75
|
static xt_generator *g_active_generator = NULL;
|
|
70
|
-
/* Filled in just before a coroutine is first entered (POSIX has no portable
|
|
71
|
-
* way to pass a pointer to `makecontext`). */
|
|
72
|
-
static xt_generator *g_boot_generator = NULL;
|
|
73
|
-
#ifdef _WIN32
|
|
74
|
-
static void *g_main_fiber = NULL;
|
|
75
|
-
#endif
|
|
76
76
|
|
|
77
77
|
int xt_is_generator(xt_value value) {
|
|
78
78
|
if (!XT_IS_OBJECT(value)) return 0;
|
|
79
79
|
return ((xt_header *)XT_GET_PTR(value))->kind == XT_OBJECT_KIND_GENERATOR;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
int xt_is_async_generator(xt_value value) {
|
|
83
|
+
if (!xt_is_generator(value)) return 0;
|
|
84
|
+
return ((xt_generator *)XT_GET_PTR(value))->is_async;
|
|
85
|
+
}
|
|
86
|
+
|
|
82
87
|
static xt_generator *xt_as_generator(xt_value value) {
|
|
83
88
|
if (!xt_is_generator(value)) return NULL;
|
|
84
89
|
return (xt_generator *)XT_GET_PTR(value);
|
|
@@ -91,38 +96,13 @@ static xt_value xt_generator_result_object(xt_value value, int done) {
|
|
|
91
96
|
return result;
|
|
92
97
|
}
|
|
93
98
|
|
|
94
|
-
static
|
|
95
|
-
|
|
96
|
-
#ifdef _WIN32
|
|
97
|
-
SwitchToFiber(gen->caller_fiber);
|
|
98
|
-
#else
|
|
99
|
-
swapcontext(&gen->ctx, &gen->caller);
|
|
100
|
-
#endif
|
|
99
|
+
static xt_value xt_generator_done_promise(xt_value value) {
|
|
100
|
+
return xt_promise_resolve(xt_generator_result_object(value, 1));
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
/* Runs on the generator's private stack. */
|
|
104
|
-
static void xt_generator_run(
|
|
105
|
-
|
|
106
|
-
/* The fiber stack is not observable from the outside; capture its bounds
|
|
107
|
-
* here (before the body allocates anything) so a collection during the body
|
|
108
|
-
* has a valid scan region. */
|
|
109
|
-
if (!gen->stack) {
|
|
110
|
-
MEMORY_BASIC_INFORMATION info;
|
|
111
|
-
uintptr_t here = (uintptr_t)&info;
|
|
112
|
-
if (VirtualQuery((LPCVOID)here, &info, sizeof(info))) {
|
|
113
|
-
/* Use the *committed* region containing the current frame: a Windows
|
|
114
|
-
* stack reserves more than it commits, and `AllocationBase + RegionSize`
|
|
115
|
-
* can fall in uncommitted memory. `BaseAddress + RegionSize` is the
|
|
116
|
-
* stack top. */
|
|
117
|
-
gen->stack = (char *)info.BaseAddress;
|
|
118
|
-
gen->stack_size = info.RegionSize;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
#endif
|
|
122
|
-
if (gen->stack && gen->stack_size && !gen->stack_pushed) {
|
|
123
|
-
xt_gc_push_stack((uintptr_t)gen->stack, (uintptr_t)gen->stack + gen->stack_size);
|
|
124
|
-
gen->stack_pushed = 1;
|
|
125
|
-
}
|
|
104
|
+
static void xt_generator_run(void *arg) {
|
|
105
|
+
xt_generator *gen = (xt_generator *)arg;
|
|
126
106
|
void *boundary = xt_try_enter();
|
|
127
107
|
if (xt_try_setjmp(boundary) == 0) {
|
|
128
108
|
xt_function *function = (xt_function *)XT_GET_PTR(gen->function);
|
|
@@ -133,92 +113,105 @@ static void xt_generator_run(xt_generator *gen) {
|
|
|
133
113
|
gen->threw = 1;
|
|
134
114
|
}
|
|
135
115
|
gen->done = 1;
|
|
136
|
-
|
|
116
|
+
xt_coroutine_leave(gen->coroutine);
|
|
137
117
|
}
|
|
138
118
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
119
|
+
/* Release the private stack once the coroutine has finished. The generator
|
|
120
|
+
* object itself stays valid; later `.next()` calls just report `done`. */
|
|
121
|
+
static void xt_generator_dispose(xt_generator *gen) {
|
|
122
|
+
xt_coroutine_release(gen->coroutine);
|
|
123
|
+
gen->coroutine = NULL;
|
|
144
124
|
}
|
|
145
|
-
|
|
146
|
-
static void
|
|
147
|
-
|
|
125
|
+
|
|
126
|
+
static void xt_generator_boot(xt_generator *gen);
|
|
127
|
+
|
|
128
|
+
/* Enter the coroutine. Returns with the coroutine suspended (yield/await) or
|
|
129
|
+
* finished. */
|
|
130
|
+
static void xt_generator_enter(xt_generator *gen) {
|
|
131
|
+
if (!gen->coroutine) xt_generator_boot(gen);
|
|
132
|
+
xt_generator *previous = g_active_generator;
|
|
133
|
+
g_active_generator = gen;
|
|
134
|
+
xt_coroutine_enter(gen->coroutine);
|
|
135
|
+
if (gen->done) xt_generator_dispose(gen);
|
|
136
|
+
g_active_generator = previous;
|
|
148
137
|
}
|
|
149
|
-
#endif
|
|
150
138
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (!
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
gen->stack = (char *)malloc(size);
|
|
159
|
-
if (!gen->stack) abort();
|
|
160
|
-
gen->stack_size = size;
|
|
161
|
-
if (getcontext(&gen->ctx) != 0) abort();
|
|
162
|
-
gen->ctx.uc_stack.ss_sp = gen->stack;
|
|
163
|
-
gen->ctx.uc_stack.ss_size = size;
|
|
164
|
-
gen->ctx.uc_link = NULL;
|
|
165
|
-
g_boot_generator = gen;
|
|
166
|
-
makecontext(&gen->ctx, xt_generator_entry, 0);
|
|
167
|
-
#endif
|
|
168
|
-
gen->booted = 1;
|
|
139
|
+
/* Settle the promise of the request that just finished. */
|
|
140
|
+
static void xt_generator_settle_pending(xt_generator *gen) {
|
|
141
|
+
if (!gen->is_async || gen->pending_promise == XT_UNDEFINED) return;
|
|
142
|
+
xt_value promise = gen->pending_promise;
|
|
143
|
+
gen->pending_promise = XT_UNDEFINED;
|
|
144
|
+
if (gen->threw) xt_promise_reject_value(promise, gen->result);
|
|
145
|
+
else xt_promise_fulfill(promise, xt_generator_result_object(gen->result, 1));
|
|
169
146
|
}
|
|
170
147
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
static void
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
148
|
+
static xt_value xt_async_enqueue(xt_generator *gen, xt_value sent, int kind);
|
|
149
|
+
|
|
150
|
+
static void xt_generator_start_next(xt_generator *gen) {
|
|
151
|
+
if (gen->request_count == 0) return;
|
|
152
|
+
xt_async_request request = gen->requests[0];
|
|
153
|
+
for (uint32_t i = 1; i < gen->request_count; i++) gen->requests[i - 1] = gen->requests[i];
|
|
154
|
+
gen->request_count--;
|
|
155
|
+
gen->pending_promise = request.promise;
|
|
156
|
+
gen->sent = request.sent;
|
|
157
|
+
gen->resume_kind = request.kind;
|
|
158
|
+
|
|
159
|
+
if (gen->done) {
|
|
160
|
+
if (request.kind == 1) xt_promise_reject_value(request.promise, request.sent);
|
|
161
|
+
else xt_promise_fulfill(request.promise, xt_generator_result_object(request.sent, 1));
|
|
162
|
+
gen->pending_promise = XT_UNDEFINED;
|
|
163
|
+
return;
|
|
178
164
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
gen->
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
165
|
+
/* A `.throw()` before the body starts rejects the request; a `.return()`
|
|
166
|
+
* before it starts completes the generator without running the body. */
|
|
167
|
+
if (!gen->started) {
|
|
168
|
+
if (request.kind == 1) {
|
|
169
|
+
gen->done = 1;
|
|
170
|
+
gen->threw = 1;
|
|
171
|
+
gen->result = request.sent;
|
|
172
|
+
xt_promise_reject_value(request.promise, request.sent);
|
|
173
|
+
gen->pending_promise = XT_UNDEFINED;
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (request.kind == 2) {
|
|
177
|
+
gen->done = 1;
|
|
178
|
+
gen->threw = 0;
|
|
179
|
+
gen->result = request.sent;
|
|
180
|
+
xt_promise_fulfill(request.promise, xt_generator_result_object(request.sent, 1));
|
|
181
|
+
gen->pending_promise = XT_UNDEFINED;
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
187
184
|
}
|
|
188
|
-
|
|
185
|
+
gen->started = 1;
|
|
186
|
+
xt_generator_enter(gen);
|
|
187
|
+
if (gen->done) xt_generator_settle_pending(gen);
|
|
189
188
|
}
|
|
190
189
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
/* Record where the current (calling) stack suspends before switching away.
|
|
196
|
-
* On Windows the first push happens inside the fiber once its stack bounds
|
|
197
|
-
* are known, so the caller's region must be marked suspended here, on the
|
|
198
|
-
* caller's own stack. */
|
|
199
|
-
xt_gc_suspend((uintptr_t)&gen);
|
|
200
|
-
if (gen->stack && gen->stack_size && !gen->stack_pushed) {
|
|
201
|
-
xt_gc_push_stack((uintptr_t)gen->stack, (uintptr_t)gen->stack + gen->stack_size);
|
|
202
|
-
gen->stack_pushed = 1;
|
|
190
|
+
/* Drain queued requests whose predecessor has already finished. */
|
|
191
|
+
static void xt_generator_drain_requests(xt_generator *gen) {
|
|
192
|
+
while (gen->pending_promise == XT_UNDEFINED && gen->request_count > 0) {
|
|
193
|
+
xt_generator_start_next(gen);
|
|
203
194
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
SwitchToFiber(gen->fiber);
|
|
211
|
-
#else
|
|
212
|
-
swapcontext(&gen->caller, &gen->ctx);
|
|
213
|
-
#endif
|
|
214
|
-
gen->saved_try_top = xt_try_mark();
|
|
215
|
-
xt_try_restore(caller_try);
|
|
216
|
-
if (gen->stack_pushed) {
|
|
217
|
-
xt_gc_pop_stack();
|
|
218
|
-
gen->stack_pushed = 0;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
static xt_value xt_async_enqueue(xt_generator *gen, xt_value sent, int kind) {
|
|
198
|
+
if (gen->done) {
|
|
199
|
+
if (kind == 1) return xt_promise_reject(sent);
|
|
200
|
+
return xt_generator_done_promise(kind == 2 ? sent : XT_UNDEFINED);
|
|
219
201
|
}
|
|
220
|
-
|
|
221
|
-
|
|
202
|
+
xt_value promise = xt_promise_create();
|
|
203
|
+
if (gen->request_count >= gen->request_capacity) {
|
|
204
|
+
uint32_t capacity = gen->request_capacity == 0 ? 4 : gen->request_capacity * 2;
|
|
205
|
+
gen->requests = (xt_async_request *)realloc(gen->requests, sizeof(xt_async_request) * capacity);
|
|
206
|
+
if (!gen->requests) abort();
|
|
207
|
+
gen->request_capacity = capacity;
|
|
208
|
+
}
|
|
209
|
+
gen->requests[gen->request_count].promise = promise;
|
|
210
|
+
gen->requests[gen->request_count].sent = sent;
|
|
211
|
+
gen->requests[gen->request_count].kind = kind;
|
|
212
|
+
gen->request_count++;
|
|
213
|
+
if (gen->pending_promise == XT_UNDEFINED) xt_generator_drain_requests(gen);
|
|
214
|
+
return promise;
|
|
222
215
|
}
|
|
223
216
|
|
|
224
217
|
/* The active generator is only reachable through this static pointer, and its
|
|
@@ -237,42 +230,57 @@ static void xt_generator_gc_register(void) {
|
|
|
237
230
|
|
|
238
231
|
void xt_generator_gc_trace(xt_header *header) {
|
|
239
232
|
xt_generator *gen = (xt_generator *)header;
|
|
240
|
-
|
|
241
|
-
|
|
233
|
+
xt_gc_mark_value(gen->function);
|
|
234
|
+
xt_gc_mark_value(gen->this_value);
|
|
235
|
+
xt_gc_mark_value(gen->sent);
|
|
236
|
+
xt_gc_mark_value(gen->result);
|
|
237
|
+
xt_gc_mark_value(gen->iter_value);
|
|
238
|
+
xt_gc_mark_value(gen->pending_promise);
|
|
239
|
+
xt_gc_mark_value(gen->resume_value);
|
|
242
240
|
if (gen->args && gen->argc > 0) {
|
|
243
241
|
xt_gc_scan_region(gen->args, sizeof(xt_value) * (size_t)gen->argc);
|
|
244
242
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
if (gen->has_caller_regs) xt_gc_scan_region(&gen->caller_regs, sizeof(gen->caller_regs));
|
|
251
|
-
#endif
|
|
243
|
+
for (uint32_t i = 0; i < gen->request_count; i++) {
|
|
244
|
+
xt_gc_mark_value(gen->requests[i].promise);
|
|
245
|
+
xt_gc_mark_value(gen->requests[i].sent);
|
|
246
|
+
}
|
|
247
|
+
xt_coroutine_gc_trace(gen->coroutine);
|
|
252
248
|
}
|
|
253
249
|
|
|
254
250
|
void xt_generator_gc_release(xt_header *header) {
|
|
255
251
|
xt_generator *gen = (xt_generator *)header;
|
|
256
252
|
free(gen->args);
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
253
|
+
free(gen->requests);
|
|
254
|
+
xt_coroutine_release(gen->coroutine);
|
|
255
|
+
gen->coroutine = NULL;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
static void xt_generator_boot(xt_generator *gen) {
|
|
259
|
+
gen->coroutine = xt_coroutine_create(xt_generator_run, gen);
|
|
262
260
|
}
|
|
263
261
|
|
|
264
262
|
xt_value xt_generator_new(xt_value function, xt_value thisValue, int32_t argc, xt_value *argv) {
|
|
265
263
|
xt_generator *gen = (xt_generator *)xt_alloc(sizeof(xt_generator), XT_OBJECT_KIND_GENERATOR);
|
|
264
|
+
xt_function *fn = (xt_function *)XT_GET_PTR(function);
|
|
266
265
|
gen->function = function;
|
|
267
266
|
gen->this_value = thisValue;
|
|
268
267
|
gen->argc = argc;
|
|
269
268
|
gen->args = NULL;
|
|
270
|
-
gen->
|
|
271
|
-
gen->stack_size = 0;
|
|
272
|
-
gen->stack_pushed = 0;
|
|
269
|
+
gen->coroutine = NULL;
|
|
273
270
|
gen->result = XT_UNDEFINED;
|
|
274
271
|
gen->sent = XT_UNDEFINED;
|
|
275
272
|
gen->iter_value = XT_UNDEFINED;
|
|
273
|
+
gen->resume_kind = 0;
|
|
274
|
+
gen->started = 0;
|
|
275
|
+
gen->done = 0;
|
|
276
|
+
gen->threw = 0;
|
|
277
|
+
gen->is_async = fn->is_async_generator;
|
|
278
|
+
gen->pending_promise = XT_UNDEFINED;
|
|
279
|
+
gen->resume_value = XT_UNDEFINED;
|
|
280
|
+
gen->await_threw = 0;
|
|
281
|
+
gen->requests = NULL;
|
|
282
|
+
gen->request_count = 0;
|
|
283
|
+
gen->request_capacity = 0;
|
|
276
284
|
if (argc > 0 && argv) {
|
|
277
285
|
gen->args = (xt_value *)malloc(sizeof(xt_value) * (size_t)argc);
|
|
278
286
|
if (!gen->args) abort();
|
|
@@ -285,13 +293,15 @@ xt_value xt_generator_new(xt_value function, xt_value thisValue, int32_t argc, x
|
|
|
285
293
|
xt_value xt_generator_next(xt_value generator, xt_value sent) {
|
|
286
294
|
xt_generator *gen = xt_as_generator(generator);
|
|
287
295
|
if (!gen) {
|
|
288
|
-
xt_throw(
|
|
296
|
+
xt_throw(xt_error_from_message("TypeError: not a generator"));
|
|
289
297
|
return XT_UNDEFINED;
|
|
290
298
|
}
|
|
299
|
+
if (gen->is_async) return xt_async_enqueue(gen, sent, 0);
|
|
291
300
|
if (gen->done) return xt_generator_result_object(XT_UNDEFINED, 1);
|
|
292
301
|
gen->sent = sent;
|
|
293
302
|
gen->resume_kind = 0;
|
|
294
|
-
|
|
303
|
+
gen->started = 1;
|
|
304
|
+
xt_generator_enter(gen);
|
|
295
305
|
if (gen->done) {
|
|
296
306
|
if (gen->threw) xt_throw(gen->result);
|
|
297
307
|
return xt_generator_result_object(gen->result, 1);
|
|
@@ -302,16 +312,18 @@ xt_value xt_generator_next(xt_value generator, xt_value sent) {
|
|
|
302
312
|
xt_value xt_generator_throw(xt_value generator, xt_value error) {
|
|
303
313
|
xt_generator *gen = xt_as_generator(generator);
|
|
304
314
|
if (!gen) {
|
|
305
|
-
xt_throw(
|
|
315
|
+
xt_throw(xt_error_from_message("TypeError: not a generator"));
|
|
306
316
|
return XT_UNDEFINED;
|
|
307
317
|
}
|
|
318
|
+
if (gen->is_async) return xt_async_enqueue(gen, error, 1);
|
|
308
319
|
if (gen->done) {
|
|
309
320
|
xt_throw(error);
|
|
310
321
|
return XT_UNDEFINED;
|
|
311
322
|
}
|
|
312
323
|
gen->sent = error;
|
|
313
324
|
gen->resume_kind = 1;
|
|
314
|
-
|
|
325
|
+
gen->started = 1;
|
|
326
|
+
xt_generator_enter(gen);
|
|
315
327
|
if (gen->done) {
|
|
316
328
|
if (gen->threw) xt_throw(gen->result);
|
|
317
329
|
return xt_generator_result_object(gen->result, 1);
|
|
@@ -322,9 +334,10 @@ xt_value xt_generator_throw(xt_value generator, xt_value error) {
|
|
|
322
334
|
xt_value xt_generator_return(xt_value generator, xt_value value) {
|
|
323
335
|
xt_generator *gen = xt_as_generator(generator);
|
|
324
336
|
if (!gen) {
|
|
325
|
-
xt_throw(
|
|
337
|
+
xt_throw(xt_error_from_message("TypeError: not a generator"));
|
|
326
338
|
return XT_UNDEFINED;
|
|
327
339
|
}
|
|
340
|
+
if (gen->is_async) return xt_async_enqueue(gen, value, 2);
|
|
328
341
|
/* Abandon the coroutine without resuming: finally blocks are not run. */
|
|
329
342
|
gen->done = 1;
|
|
330
343
|
gen->threw = 0;
|
|
@@ -339,21 +352,84 @@ xt_value xt_yield(xt_value value) {
|
|
|
339
352
|
xt_generator *gen = g_active_generator;
|
|
340
353
|
if (!gen || gen->done) return XT_UNDEFINED;
|
|
341
354
|
gen->result = value;
|
|
342
|
-
|
|
355
|
+
/* Settle the async `.next()` request that produced this yield. A pending
|
|
356
|
+
* `.throw(e)` must *not* settle it: if the body catches the error it may
|
|
357
|
+
* yield again, and only that next yield (or the escaped exception) settles
|
|
358
|
+
* the request. */
|
|
359
|
+
if (gen->is_async && gen->resume_kind != 1 && gen->pending_promise != XT_UNDEFINED) {
|
|
360
|
+
xt_value promise = gen->pending_promise;
|
|
361
|
+
gen->pending_promise = XT_UNDEFINED;
|
|
362
|
+
xt_promise_fulfill(promise, xt_generator_result_object(value, gen->resume_kind == 2));
|
|
363
|
+
}
|
|
364
|
+
/* The resume kind may change while suspended: control returns here only
|
|
365
|
+
* when the next `.next()` / `.throw()` / `.return()` resumes the coroutine,
|
|
366
|
+
* so the checks below must sit after the context switch. */
|
|
367
|
+
xt_coroutine_leave(gen->coroutine);
|
|
343
368
|
if (gen->resume_kind == 1) {
|
|
369
|
+
gen->resume_kind = 0;
|
|
344
370
|
xt_throw(gen->sent);
|
|
345
371
|
return XT_UNDEFINED;
|
|
346
372
|
}
|
|
347
373
|
if (gen->resume_kind == 2) {
|
|
374
|
+
gen->resume_kind = 0;
|
|
348
375
|
gen->done = 1;
|
|
349
376
|
gen->threw = 0;
|
|
350
377
|
gen->result = gen->sent;
|
|
351
|
-
|
|
378
|
+
if (gen->is_async && gen->pending_promise != XT_UNDEFINED) {
|
|
379
|
+
xt_value promise = gen->pending_promise;
|
|
380
|
+
gen->pending_promise = XT_UNDEFINED;
|
|
381
|
+
xt_promise_fulfill(promise, xt_generator_result_object(gen->sent, 1));
|
|
382
|
+
}
|
|
383
|
+
xt_coroutine_leave(gen->coroutine);
|
|
352
384
|
return XT_UNDEFINED;
|
|
353
385
|
}
|
|
354
386
|
return gen->sent;
|
|
355
387
|
}
|
|
356
388
|
|
|
389
|
+
/* `await value` inside an async generator. The generator's current `.next()`
|
|
390
|
+
* promise stays pending; when the awaited promise settles the coroutine is
|
|
391
|
+
* resumed and this function returns the settlement (or throws a rejection). */
|
|
392
|
+
int xt_generator_await(xt_value value, xt_value *result) {
|
|
393
|
+
xt_generator *gen = g_active_generator;
|
|
394
|
+
if (!gen || !gen->is_async || gen->done || !gen->coroutine) return 0;
|
|
395
|
+
/* A nested async function inside the generator runs on its own coroutine;
|
|
396
|
+
* its awaits must not suspend the generator. */
|
|
397
|
+
if (!xt_coroutine_is_current(gen->coroutine)) return 0;
|
|
398
|
+
int state = xt_promise_state_of(value);
|
|
399
|
+
if (state == XT_PROMISE_PENDING) {
|
|
400
|
+
gen->await_threw = 0;
|
|
401
|
+
gen->resume_value = XT_UNDEFINED;
|
|
402
|
+
xt_promise_add_async_waiter(value, gen);
|
|
403
|
+
xt_coroutine_leave(gen->coroutine);
|
|
404
|
+
} else {
|
|
405
|
+
int rejected = state == XT_PROMISE_REJECTED;
|
|
406
|
+
xt_value settled = (state == XT_PROMISE_FULFILLED || rejected)
|
|
407
|
+
? xt_promise_value_of(value)
|
|
408
|
+
: value;
|
|
409
|
+
gen->await_threw = rejected;
|
|
410
|
+
gen->resume_value = settled;
|
|
411
|
+
xt_promise_queue_async_wake(gen, settled, rejected);
|
|
412
|
+
xt_coroutine_leave(gen->coroutine);
|
|
413
|
+
}
|
|
414
|
+
if (gen->await_threw) {
|
|
415
|
+
gen->await_threw = 0;
|
|
416
|
+
xt_throw(gen->resume_value);
|
|
417
|
+
return 1;
|
|
418
|
+
}
|
|
419
|
+
*result = gen->resume_value;
|
|
420
|
+
return 1;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
void xt_generator_wake(void *pointer, xt_value value, int rejected) {
|
|
424
|
+
xt_generator *gen = (xt_generator *)pointer;
|
|
425
|
+
if (!gen || gen->done || !gen->coroutine) return;
|
|
426
|
+
gen->resume_value = value;
|
|
427
|
+
gen->await_threw = rejected;
|
|
428
|
+
xt_generator_enter(gen);
|
|
429
|
+
if (gen->done) xt_generator_settle_pending(gen);
|
|
430
|
+
else xt_generator_drain_requests(gen);
|
|
431
|
+
}
|
|
432
|
+
|
|
357
433
|
/* `yield* delegate`: relay every value the delegate produces. */
|
|
358
434
|
xt_value xt_yield_star(xt_value delegate) {
|
|
359
435
|
xt_value nextName = xt_string_from_cstr("next");
|
|
@@ -385,7 +461,7 @@ xt_value xt_yield_star(xt_value delegate) {
|
|
|
385
461
|
/* `for...of` step for generators: pull and cache the next value. */
|
|
386
462
|
int xt_generator_has_next(xt_value generator) {
|
|
387
463
|
xt_generator *gen = xt_as_generator(generator);
|
|
388
|
-
if (!gen || gen->done) return 0;
|
|
464
|
+
if (!gen || gen->done || gen->is_async) return 0;
|
|
389
465
|
xt_value step = xt_generator_next(generator, XT_UNDEFINED);
|
|
390
466
|
if (xt_truthy(xt_get(step, xt_string_from_cstr("done")))) return 0;
|
|
391
467
|
gen->iter_value = xt_get(step, xt_string_from_cstr("value"));
|
|
@@ -396,3 +472,85 @@ xt_value xt_generator_iter_value(xt_value generator) {
|
|
|
396
472
|
xt_generator *gen = xt_as_generator(generator);
|
|
397
473
|
return gen ? gen->iter_value : XT_UNDEFINED;
|
|
398
474
|
}
|
|
475
|
+
|
|
476
|
+
xt_value xt_function_set_generator(xt_value value) {
|
|
477
|
+
if (XT_IS_FUNCTION(value)) ((xt_function *)XT_GET_PTR(value))->is_generator = 1;
|
|
478
|
+
return value;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
xt_value xt_function_set_async_generator(xt_value value) {
|
|
482
|
+
if (XT_IS_FUNCTION(value)) {
|
|
483
|
+
xt_function *function = (xt_function *)XT_GET_PTR(value);
|
|
484
|
+
function->is_generator = 1;
|
|
485
|
+
function->is_async_generator = 1;
|
|
486
|
+
}
|
|
487
|
+
return value;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/* -- async iteration ------------------------------------------------------ */
|
|
491
|
+
|
|
492
|
+
static xt_value xt_async_iterator_self(xt_value thisValue, xt_value env, int32_t argc,
|
|
493
|
+
xt_value *argv) {
|
|
494
|
+
(void)env;
|
|
495
|
+
(void)argc;
|
|
496
|
+
(void)argv;
|
|
497
|
+
return thisValue;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
xt_value xt_async_iterator_method(void) {
|
|
501
|
+
static xt_value method = XT_UNDEFINED;
|
|
502
|
+
if (!XT_IS_FUNCTION(method)) {
|
|
503
|
+
method = xt_closure_new((void *)xt_async_iterator_self, 0, NULL);
|
|
504
|
+
xt_gc_add_root(&method);
|
|
505
|
+
}
|
|
506
|
+
return method;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
xt_value xt_async_iter_open(xt_value value) {
|
|
510
|
+
if (xt_is_async_generator(value)) return value;
|
|
511
|
+
/* A user object may implement `[Symbol.asyncIterator]()`. */
|
|
512
|
+
if (XT_IS_OBJECT(value) || XT_IS_ARRAY(value) || XT_IS_FUNCTION(value)) {
|
|
513
|
+
xt_value method = xt_get(value, xt_symbol_well_known("asyncIterator"));
|
|
514
|
+
if (XT_IS_FUNCTION(method)) {
|
|
515
|
+
xt_value iterator = xt_call_with_this(method, value, 0, NULL);
|
|
516
|
+
if (XT_IS_OBJECT(iterator) || XT_IS_FUNCTION(iterator)) return iterator;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
/* Fall back to the synchronous protocol and adapt each step. */
|
|
520
|
+
xt_async_iterator_state *state =
|
|
521
|
+
(xt_async_iterator_state *)xt_alloc(sizeof(xt_async_iterator_state),
|
|
522
|
+
XT_OBJECT_KIND_ASYNC_ITERATOR);
|
|
523
|
+
state->iterator = xt_iter_open(value);
|
|
524
|
+
state->index = xt_number(0);
|
|
525
|
+
state->done = 0;
|
|
526
|
+
return XT_FROM_PTR(XT_TAG_OBJECT, state);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
static int xt_is_async_iterator_state(xt_value value) {
|
|
530
|
+
return XT_IS_OBJECT(value) &&
|
|
531
|
+
((xt_header *)XT_GET_PTR(value))->kind == XT_OBJECT_KIND_ASYNC_ITERATOR;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
xt_value xt_async_iter_next(xt_value iterator) {
|
|
535
|
+
if (xt_is_async_generator(iterator)) return xt_generator_next(iterator, XT_UNDEFINED);
|
|
536
|
+
if (xt_is_async_iterator_state(iterator)) {
|
|
537
|
+
xt_async_iterator_state *state = (xt_async_iterator_state *)XT_GET_PTR(iterator);
|
|
538
|
+
if (state->done) return xt_promise_resolve(xt_generator_result_object(XT_UNDEFINED, 1));
|
|
539
|
+
if (!xt_truthy(xt_iter_has(state->iterator, state->index))) {
|
|
540
|
+
state->done = 1;
|
|
541
|
+
return xt_promise_resolve(xt_generator_result_object(XT_UNDEFINED, 1));
|
|
542
|
+
}
|
|
543
|
+
xt_value value = xt_iter_value(state->iterator, state->index);
|
|
544
|
+
state->index = xt_add(state->index, xt_number(1));
|
|
545
|
+
return xt_promise_resolve(xt_generator_result_object(value, 0));
|
|
546
|
+
}
|
|
547
|
+
xt_value step = xt_call_method(iterator, xt_string_from_cstr("next"), 0, NULL);
|
|
548
|
+
if (xt_promise_state_of(step) >= 0) return step;
|
|
549
|
+
return xt_promise_resolve(step);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
void xt_async_iterator_gc_trace(xt_header *header) {
|
|
553
|
+
xt_async_iterator_state *state = (xt_async_iterator_state *)header;
|
|
554
|
+
xt_gc_mark_value(state->iterator);
|
|
555
|
+
xt_gc_mark_value(state->index);
|
|
556
|
+
}
|