xbintsc 0.5.22 → 0.5.31
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 +12 -3
- package/README.md +46 -11
- package/README.zh-CN.md +32 -6
- package/dist/scripts/support-matrix.d.ts +18 -0
- package/dist/scripts/support-matrix.js +141 -0
- package/dist/scripts/support-matrix.js.map +1 -0
- package/dist/src/ast/common.d.ts +2 -2
- package/dist/src/ast/declarations.d.ts +7 -1
- package/dist/src/ast/expressions.d.ts +5 -0
- package/dist/src/ast/kinds.d.ts +2 -0
- package/dist/src/ast/kinds.js +2 -0
- package/dist/src/ast/kinds.js.map +1 -1
- package/dist/src/binder/binder.d.ts +2 -1
- package/dist/src/binder/binder.js +2 -0
- package/dist/src/binder/binder.js.map +1 -1
- package/dist/src/binder/declarations.d.ts +9 -0
- package/dist/src/binder/declarations.js +64 -0
- package/dist/src/binder/declarations.js.map +1 -1
- package/dist/src/binder/references.js +85 -3
- package/dist/src/binder/references.js.map +1 -1
- package/dist/src/binder/types.d.ts +32 -0
- package/dist/src/binder/types.js.map +1 -1
- package/dist/src/canonical.d.ts +29 -0
- package/dist/src/canonical.js +35 -0
- package/dist/src/canonical.js.map +1 -0
- package/dist/src/checker/assignability.d.ts +13 -0
- package/dist/src/checker/assignability.js +146 -0
- package/dist/src/checker/assignability.js.map +1 -0
- package/dist/src/checker/calls.d.ts +13 -0
- package/dist/src/checker/calls.js +127 -0
- package/dist/src/checker/calls.js.map +1 -0
- package/dist/src/checker/checker.d.ts +26 -0
- package/dist/src/checker/checker.js +31 -0
- package/dist/src/checker/checker.js.map +1 -0
- package/dist/src/checker/declarations.d.ts +9 -0
- package/dist/src/checker/declarations.js +15 -0
- package/dist/src/checker/declarations.js.map +1 -0
- package/dist/src/checker/flow.d.ts +21 -0
- package/dist/src/checker/flow.js +241 -0
- package/dist/src/checker/flow.js.map +1 -0
- package/dist/src/checker/globals.d.ts +9 -0
- package/dist/src/checker/globals.js +29 -0
- package/dist/src/checker/globals.js.map +1 -0
- package/dist/src/checker/source.d.ts +38 -0
- package/dist/src/checker/source.js +48 -0
- package/dist/src/checker/source.js.map +1 -0
- package/dist/src/checker/type-infer.d.ts +18 -0
- package/dist/src/checker/type-infer.js +173 -0
- package/dist/src/checker/type-infer.js.map +1 -0
- package/dist/src/checker/type-model.d.ts +73 -0
- package/dist/src/checker/type-model.js +151 -0
- package/dist/src/checker/type-model.js.map +1 -0
- package/dist/src/checker/type-system.d.ts +58 -0
- package/dist/src/checker/type-system.js +569 -0
- package/dist/src/checker/type-system.js.map +1 -0
- package/dist/src/checker/typecheck-types.d.ts +22 -0
- package/dist/src/checker/typecheck-types.js +109 -0
- package/dist/src/checker/typecheck-types.js.map +1 -0
- package/dist/src/checker/typecheck.d.ts +62 -0
- package/dist/src/checker/typecheck.js +574 -0
- package/dist/src/checker/typecheck.js.map +1 -0
- package/dist/src/checker/undefined.d.ts +14 -0
- package/dist/src/checker/undefined.js +32 -0
- package/dist/src/checker/undefined.js.map +1 -0
- package/dist/src/checker/walk.d.ts +10 -0
- package/dist/src/checker/walk.js +15 -0
- package/dist/src/checker/walk.js.map +1 -0
- package/dist/src/cli/help.d.ts +7 -0
- package/dist/src/cli/help.js +64 -0
- package/dist/src/cli/help.js.map +1 -0
- package/dist/src/cli/hints.js +13 -1
- package/dist/src/cli/hints.js.map +1 -1
- package/dist/src/cli/main.js +12 -48
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/codegen/generator/calls/access.js +8 -8
- package/dist/src/codegen/generator/calls/access.js.map +1 -1
- package/dist/src/codegen/generator/calls/invocation.js +9 -4
- package/dist/src/codegen/generator/calls/invocation.js.map +1 -1
- package/dist/src/codegen/generator/calls/super.d.ts +9 -1
- package/dist/src/codegen/generator/calls/super.js +56 -5
- package/dist/src/codegen/generator/calls/super.js.map +1 -1
- package/dist/src/codegen/generator/context.d.ts +13 -2
- package/dist/src/codegen/generator/context.js +25 -19
- package/dist/src/codegen/generator/context.js.map +1 -1
- package/dist/src/codegen/generator/debug.js +2 -1
- package/dist/src/codegen/generator/debug.js.map +1 -1
- package/dist/src/codegen/generator/expressions/primary.d.ts +4 -1
- package/dist/src/codegen/generator/expressions/primary.js +68 -8
- package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
- package/dist/src/codegen/generator/generator.js +11 -1
- package/dist/src/codegen/generator/generator.js.map +1 -1
- package/dist/src/codegen/generator/module.d.ts +2 -0
- package/dist/src/codegen/generator/module.js +62 -26
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/state.d.ts +11 -1
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/statements/variables.js +20 -3
- package/dist/src/codegen/generator/statements/variables.js.map +1 -1
- package/dist/src/codegen/generator/tables.d.ts +2 -0
- package/dist/src/codegen/generator/tables.js +4 -0
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/driver/build-key.d.ts +2 -0
- package/dist/src/driver/build-key.js +1 -0
- package/dist/src/driver/build-key.js.map +1 -1
- package/dist/src/driver/bundler/graph.js +5 -1
- package/dist/src/driver/bundler/graph.js.map +1 -1
- package/dist/src/driver/bundler/merge.js +16 -1
- package/dist/src/driver/bundler/merge.js.map +1 -1
- package/dist/src/driver/bundler/types.d.ts +12 -0
- package/dist/src/driver/compiler.d.ts +1 -1
- package/dist/src/driver/compiler.js +4 -0
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/fingerprint.js +2 -1
- package/dist/src/driver/fingerprint.js.map +1 -1
- package/dist/src/driver/frontend.d.ts +8 -6
- package/dist/src/driver/frontend.js +4 -0
- package/dist/src/driver/frontend.js.map +1 -1
- package/dist/src/driver/options.d.ts +6 -0
- package/dist/src/driver/version.d.ts +1 -1
- package/dist/src/driver/version.js +1 -1
- package/dist/src/extensions/catalog.js +2 -1
- package/dist/src/extensions/catalog.js.map +1 -1
- package/dist/src/extensions/gui/html.js +20 -6
- package/dist/src/extensions/gui/html.js.map +1 -1
- package/dist/src/extensions/gui/index.js +63 -0
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/media/index.d.ts +27 -0
- package/dist/src/extensions/media/index.js +60 -0
- package/dist/src/extensions/media/index.js.map +1 -0
- package/dist/src/extensions/registry.d.ts +50 -0
- package/dist/src/extensions/registry.js +26 -0
- package/dist/src/extensions/registry.js.map +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/parser/declarations/classes.js +7 -0
- package/dist/src/parser/declarations/classes.js.map +1 -1
- package/dist/src/parser/expressions.js +14 -1
- package/dist/src/parser/expressions.js.map +1 -1
- package/dist/src/parser/literals.js +6 -2
- package/dist/src/parser/literals.js.map +1 -1
- package/dist/tests/binder/binder.test.js +29 -0
- package/dist/tests/binder/binder.test.js.map +1 -1
- package/dist/tests/canonical.test.d.ts +1 -0
- package/dist/tests/canonical.test.js +19 -0
- package/dist/tests/canonical.test.js.map +1 -0
- package/dist/tests/checker/checker.test.d.ts +1 -0
- package/dist/tests/checker/checker.test.js +245 -0
- package/dist/tests/checker/checker.test.js.map +1 -0
- package/dist/tests/cli/check.test.js +20 -0
- package/dist/tests/cli/check.test.js.map +1 -1
- package/dist/tests/cli/hints.test.js +15 -0
- package/dist/tests/cli/hints.test.js.map +1 -1
- package/dist/tests/cli/process.test.js +12 -0
- package/dist/tests/cli/process.test.js.map +1 -1
- package/dist/tests/conformance/matrix.test.d.ts +6 -0
- package/dist/tests/conformance/matrix.test.js +23 -0
- package/dist/tests/conformance/matrix.test.js.map +1 -0
- package/dist/tests/conformance/test262/manifest.d.ts +115 -0
- package/dist/tests/conformance/test262/manifest.js +257 -0
- package/dist/tests/conformance/test262/manifest.js.map +1 -0
- package/dist/tests/conformance/test262.test.d.ts +11 -0
- package/dist/tests/conformance/test262.test.js +74 -0
- package/dist/tests/conformance/test262.test.js.map +1 -0
- package/dist/tests/docs/structure.test.js +9 -11
- package/dist/tests/docs/structure.test.js.map +1 -1
- package/dist/tests/e2e/child-process.test.js +3 -2
- package/dist/tests/e2e/child-process.test.js.map +1 -1
- package/dist/tests/e2e/compile-builtins.test.js +21 -0
- package/dist/tests/e2e/compile-builtins.test.js.map +1 -1
- package/dist/tests/e2e/compile-objects-classes.test.js +54 -0
- package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
- package/dist/tests/e2e/differential-syntax.test.d.ts +5 -0
- package/dist/tests/e2e/differential-syntax.test.js +95 -0
- package/dist/tests/e2e/differential-syntax.test.js.map +1 -0
- package/dist/tests/e2e/differential-values.test.js +15 -0
- package/dist/tests/e2e/differential-values.test.js.map +1 -1
- package/dist/tests/e2e/gui-browser.test.d.ts +13 -0
- package/dist/tests/e2e/gui-browser.test.js +163 -0
- package/dist/tests/e2e/gui-browser.test.js.map +1 -0
- package/dist/tests/e2e/gui-example-browser.test.js +2 -2
- package/dist/tests/e2e/gui-example-browser.test.js.map +1 -1
- package/dist/tests/e2e/gui-example-canvas.test.js +8 -5
- package/dist/tests/e2e/gui-example-canvas.test.js.map +1 -1
- package/dist/tests/e2e/gui-example-svg.test.js +4 -3
- package/dist/tests/e2e/gui-example-svg.test.js.map +1 -1
- package/dist/tests/e2e/gui-example.test.js +4 -3
- package/dist/tests/e2e/gui-example.test.js.map +1 -1
- package/dist/tests/e2e/gui-helpers.d.ts +3 -0
- package/dist/tests/e2e/gui-helpers.js +6 -3
- package/dist/tests/e2e/gui-helpers.js.map +1 -1
- package/dist/tests/e2e/gui-media-disabled.test.d.ts +9 -0
- package/dist/tests/e2e/gui-media-disabled.test.js +42 -0
- package/dist/tests/e2e/gui-media-disabled.test.js.map +1 -0
- package/dist/tests/e2e/gui-media.test.d.ts +6 -4
- package/dist/tests/e2e/gui-media.test.js +20 -16
- package/dist/tests/e2e/gui-media.test.js.map +1 -1
- package/dist/tests/e2e/harness.d.ts +9 -0
- package/dist/tests/e2e/harness.js +14 -2
- package/dist/tests/e2e/harness.js.map +1 -1
- package/dist/tests/e2e/native-extensions.test.js +2 -1
- package/dist/tests/e2e/native-extensions.test.js.map +1 -1
- package/dist/tests/e2e/property-descriptors.test.js +20 -0
- package/dist/tests/e2e/property-descriptors.test.js.map +1 -1
- package/dist/tests/e2e/unicode-output.test.d.ts +16 -0
- package/dist/tests/e2e/unicode-output.test.js +67 -0
- package/dist/tests/e2e/unicode-output.test.js.map +1 -0
- package/dist/tests/e2e/weak-collections.test.js +16 -2
- package/dist/tests/e2e/weak-collections.test.js.map +1 -1
- package/dist/tests/extensions/media.test.d.ts +1 -0
- package/dist/tests/extensions/media.test.js +58 -0
- package/dist/tests/extensions/media.test.js.map +1 -0
- package/dist/tests/extensions/registry.test.js +8 -0
- package/dist/tests/extensions/registry.test.js.map +1 -1
- package/dist/tests/helpers.d.ts +1 -0
- package/dist/tests/helpers.js +1 -0
- package/dist/tests/helpers.js.map +1 -1
- package/dist/tests/lexer/identifiers.test.js +12 -0
- package/dist/tests/lexer/identifiers.test.js.map +1 -1
- package/dist/tests/lexer/scanner.test.js +8 -0
- package/dist/tests/lexer/scanner.test.js.map +1 -1
- package/dist/tests/lexer/strings.test.js +30 -0
- package/dist/tests/lexer/strings.test.js.map +1 -1
- package/dist/tests/parser/declarations.test.js +20 -0
- package/dist/tests/parser/declarations.test.js.map +1 -1
- package/dist/tests/parser/expressions.test.js +36 -0
- package/dist/tests/parser/expressions.test.js.map +1 -1
- package/dist/tests/platform.d.ts +32 -0
- package/dist/tests/platform.js +40 -0
- package/dist/tests/platform.js.map +1 -0
- package/dist/tests/platform.test.d.ts +12 -0
- package/dist/tests/platform.test.js +51 -0
- package/dist/tests/platform.test.js.map +1 -0
- package/dist/tests/version.test.js +4 -4
- package/dist/tests/version.test.js.map +1 -1
- package/doc/ai/README.md +10 -4
- package/doc/ai/build-recipe.md +1 -0
- package/doc/ai/cli.md +18 -6
- package/doc/ai/contributing.md +59 -2
- package/doc/ai/extensions.md +46 -23
- package/doc/ai/language-support.md +25 -16
- package/doc/ai/troubleshooting.md +9 -0
- package/doc/ai/zh-CN/README.md +9 -4
- package/doc/ai/zh-CN/build-recipe.md +1 -0
- package/doc/ai/zh-CN/cli.md +14 -4
- package/doc/ai/zh-CN/contributing.md +49 -3
- package/doc/ai/zh-CN/extensions.md +29 -8
- package/doc/ai/zh-CN/language-support.md +23 -14
- package/doc/ai/zh-CN/troubleshooting.md +8 -0
- package/doc/gui/api.md +45 -0
- package/doc/gui/build.md +37 -21
- package/doc/gui/known-issues.md +17 -6
- package/doc/gui/media.md +26 -11
- package/doc/gui/runtime.md +18 -0
- package/doc/gui-scripts.md +7 -0
- package/doc/gui.md +43 -33
- package/doc/implemented/binder.md +2 -0
- package/doc/implemented/checker.md +117 -0
- package/doc/implemented/cli.md +13 -1
- package/doc/implemented/codegen.md +3 -2
- package/doc/implemented/driver.md +2 -2
- package/doc/implemented/operators.md +2 -1
- package/doc/implemented/parser.md +3 -2
- package/doc/implemented/pipeline.md +8 -1
- package/doc/implemented/stdlib.md +2 -1
- package/doc/implemented/tests.md +3 -1
- package/doc/implemented.md +2 -0
- package/doc/npm-package.md +417 -0
- package/doc/requirements.md +4 -1
- package/doc/support-matrix.md +83 -0
- package/doc/unimplemented/classes.md +3 -0
- package/doc/unimplemented/deviations.md +3 -2
- package/doc/unimplemented/toolchain.md +1 -1
- package/doc/unimplemented/types.md +24 -8
- package/doc/unimplemented.md +1 -1
- package/doc/zh-CN/gui/api.md +41 -0
- package/doc/zh-CN/gui/build.md +28 -16
- package/doc/zh-CN/gui/known-issues.md +13 -5
- package/doc/zh-CN/gui/media.md +21 -10
- package/doc/zh-CN/gui/runtime.md +16 -0
- package/doc/zh-CN/gui-scripts.md +5 -0
- package/doc/zh-CN/gui.md +37 -32
- package/doc/zh-CN/implemented/binder.md +2 -0
- package/doc/zh-CN/implemented/checker.md +99 -0
- package/doc/zh-CN/implemented/cli.md +12 -1
- package/doc/zh-CN/implemented/codegen.md +3 -2
- package/doc/zh-CN/implemented/driver.md +2 -2
- package/doc/zh-CN/implemented/operators.md +1 -1
- package/doc/zh-CN/implemented/parser.md +3 -2
- package/doc/zh-CN/implemented/pipeline.md +3 -1
- package/doc/zh-CN/implemented/stdlib.md +2 -1
- package/doc/zh-CN/implemented/tests.md +3 -1
- package/doc/zh-CN/implemented.md +2 -0
- package/doc/zh-CN/npm-package.md +391 -0
- package/doc/zh-CN/post/announce.md +47 -47
- package/doc/zh-CN/requirements.md +4 -1
- package/doc/zh-CN/support-matrix.md +82 -0
- package/doc/zh-CN/unimplemented/classes.md +3 -0
- package/doc/zh-CN/unimplemented/deviations.md +3 -2
- package/doc/zh-CN/unimplemented/toolchain.md +1 -1
- package/doc/zh-CN/unimplemented/types.md +16 -6
- package/doc/zh-CN/unimplemented.md +1 -1
- package/llms.txt +4 -1
- package/package.json +3 -1
- package/runtime/ext_gui/audio.cpp +316 -0
- package/runtime/ext_gui/browser.cpp +547 -0
- package/runtime/ext_gui/browser_escape.cpp +85 -0
- package/runtime/ext_gui/browser_loop.cpp +83 -0
- package/runtime/ext_gui/canvas.cpp +9 -3
- package/runtime/ext_gui/canvas_raster.cpp +19 -1
- package/runtime/ext_gui/dom_api.cpp +36 -0
- package/runtime/ext_gui/dom_api_document.cpp +96 -5
- package/runtime/ext_gui/dom_api_events.cpp +20 -0
- package/runtime/ext_gui/dom_api_internal.h +19 -0
- package/runtime/ext_gui/dom_api_proto.cpp +6 -0
- package/runtime/ext_gui/gui.cpp +90 -23
- package/runtime/ext_gui/gui_engine.h +44 -0
- package/runtime/ext_gui/gui_media.cpp +69 -2
- package/runtime/ext_gui/media.cpp +34 -488
- package/runtime/ext_gui/media.h +54 -19
- package/runtime/ext_gui/media_api.h +65 -0
- package/runtime/ext_gui/window.cpp +9 -0
- package/runtime/ext_media/media.cpp +507 -0
- package/runtime/ext_media/media_bridge.c +35 -0
- package/runtime/ext_node/path/path.c +7 -7
- package/runtime/ext_node/url/url.c +4 -2
- package/runtime/rt.h +15 -0
- package/runtime/xt_constructors.c +2 -1
- package/runtime/xt_containers/objects.inc +22 -2
- package/runtime/xt_io/exception.inc +4 -2
- package/runtime/xt_stdlib/math.inc +62 -0
- package/runtime/xt_stdlib2/date.inc +7 -1
- package/runtime/xt_stdlib2/objects.inc +14 -0
- package/scripts/build-gui.ts +6 -72
- package/scripts/build-media.ts +245 -0
- package/scripts/support-matrix.ts +167 -0
- package/src/ast/common.ts +2 -0
- package/src/ast/declarations.ts +12 -1
- package/src/ast/expressions.ts +6 -0
- package/src/ast/kinds.ts +2 -0
- package/src/binder/binder.ts +3 -0
- package/src/binder/declarations.ts +70 -0
- package/src/binder/references.ts +84 -3
- package/src/binder/types.ts +30 -0
- package/src/canonical.ts +37 -0
- package/src/checker/assignability.ts +134 -0
- package/src/checker/calls.ts +135 -0
- package/src/checker/checker.ts +47 -0
- package/src/checker/declarations.ts +26 -0
- package/src/checker/flow.ts +236 -0
- package/src/checker/globals.ts +40 -0
- package/src/checker/source.ts +53 -0
- package/src/checker/type-infer.ts +185 -0
- package/src/checker/type-model.ts +212 -0
- package/src/checker/type-system.ts +578 -0
- package/src/checker/typecheck-types.ts +112 -0
- package/src/checker/typecheck.ts +586 -0
- package/src/checker/undefined.ts +43 -0
- package/src/checker/walk.ts +16 -0
- package/src/cli/help.ts +65 -0
- package/src/cli/hints.ts +13 -1
- package/src/cli/main.ts +12 -49
- package/src/codegen/generator/calls/access.ts +8 -8
- package/src/codegen/generator/calls/invocation.ts +8 -5
- package/src/codegen/generator/calls/super.ts +67 -5
- package/src/codegen/generator/context.ts +31 -19
- package/src/codegen/generator/debug.ts +2 -1
- package/src/codegen/generator/expressions/primary.ts +84 -13
- package/src/codegen/generator/generator.ts +11 -1
- package/src/codegen/generator/module.ts +65 -24
- package/src/codegen/generator/state.ts +11 -1
- package/src/codegen/generator/statements/variables.ts +20 -3
- package/src/codegen/generator/tables.ts +5 -0
- package/src/driver/build-key.ts +3 -0
- package/src/driver/bundler/graph.ts +6 -2
- package/src/driver/bundler/merge.ts +14 -1
- package/src/driver/bundler/types.ts +13 -0
- package/src/driver/compiler.ts +5 -1
- package/src/driver/fingerprint.ts +2 -1
- package/src/driver/frontend.ts +13 -2
- package/src/driver/options.ts +6 -0
- package/src/driver/version.ts +1 -1
- package/src/extensions/catalog.ts +2 -1
- package/src/extensions/gui/html.ts +23 -10
- package/src/extensions/gui/index.ts +65 -0
- package/src/extensions/media/index.ts +67 -0
- package/src/extensions/registry.ts +72 -0
- package/src/index.ts +2 -0
- package/src/parser/declarations/classes.ts +7 -0
- package/src/parser/expressions.ts +13 -1
- package/src/parser/literals.ts +6 -2
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Render `doc/support-matrix.md` and its Chinese mirror from the vendored
|
|
4
|
+
* test262 catalogue.
|
|
5
|
+
*
|
|
6
|
+
* The catalogue is executable evidence: `tests/conformance/test262.test.ts`
|
|
7
|
+
* compiles and runs every supported case (unmodified test262 files) and
|
|
8
|
+
* requires every unsupported case to fail with the listed diagnostic code.
|
|
9
|
+
* This script turns the same catalogue into the human-readable table, so the
|
|
10
|
+
* document cannot claim a feature the compiler does not exercise.
|
|
11
|
+
*
|
|
12
|
+
* Usage: npm run docs:matrix
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { writeFileSync } from "node:fs";
|
|
16
|
+
import { dirname, resolve } from "node:path";
|
|
17
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
18
|
+
import {
|
|
19
|
+
SUPPORT_AREAS,
|
|
20
|
+
SUPPORTED_CASES,
|
|
21
|
+
UNSUPPORTED_CASES,
|
|
22
|
+
type SupportArea,
|
|
23
|
+
} from "../tests/conformance/test262/manifest.js";
|
|
24
|
+
|
|
25
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
26
|
+
|
|
27
|
+
type Language = "en" | "zh";
|
|
28
|
+
|
|
29
|
+
export const MATRIX_FILES: Readonly<Record<Language, string>> = {
|
|
30
|
+
en: "doc/support-matrix.md",
|
|
31
|
+
zh: "doc/zh-CN/support-matrix.md",
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const TEST262_COMMIT = "d53ebc8b1931d9f1541e43d59650776e4b766248";
|
|
35
|
+
|
|
36
|
+
function docLink(area: SupportArea, language: Language): string {
|
|
37
|
+
const relative = area.doc.startsWith("doc/") ? area.doc.slice("doc/".length) : area.doc;
|
|
38
|
+
return language === "en" ? relative : `../${relative}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function areaTitle(area: SupportArea, language: Language): string {
|
|
42
|
+
return language === "en" ? area.title : area.titleZh;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function count(area: SupportArea, cases: readonly { readonly area: string }[]): number {
|
|
46
|
+
return cases.filter((testCase) => testCase.area === area.id).length;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function rowsFor(language: Language): string {
|
|
50
|
+
return SUPPORT_AREAS.map((area) => {
|
|
51
|
+
const supported = count(area, SUPPORTED_CASES);
|
|
52
|
+
const unsupported = count(area, UNSUPPORTED_CASES);
|
|
53
|
+
return `| ${areaTitle(area, language)} | ${supported} | ${unsupported} | [${language === "en" ? "reference" : "参考"}](${docLink(area, language)}) |`;
|
|
54
|
+
}).join("\n");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function supportedTable(language: Language): string {
|
|
58
|
+
const header =
|
|
59
|
+
language === "en"
|
|
60
|
+
? "| test262 case | Area | What it pins down |\n| --- | --- | --- |"
|
|
61
|
+
: "| test262 用例 | 领域 | 固化的行为 |\n| --- | --- | --- |";
|
|
62
|
+
const rows = SUPPORTED_CASES.map((testCase) => {
|
|
63
|
+
const area = SUPPORT_AREAS.find((candidate) => candidate.id === testCase.area)!;
|
|
64
|
+
const claim = language === "en" ? testCase.claim : testCase.claimZh;
|
|
65
|
+
return `| \`${testCase.path}\` | ${areaTitle(area, language)} | ${claim} |`;
|
|
66
|
+
});
|
|
67
|
+
return [header, ...rows].join("\n");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function unsupportedTable(language: Language): string {
|
|
71
|
+
const header =
|
|
72
|
+
language === "en"
|
|
73
|
+
? "| test262 case | Area | Diagnostic | Why |\n| --- | --- | ---: | --- |"
|
|
74
|
+
: "| test262 用例 | 领域 | 诊断码 | 原因 |\n| --- | --- | ---: | --- |";
|
|
75
|
+
const rows = UNSUPPORTED_CASES.map((testCase) => {
|
|
76
|
+
const area = SUPPORT_AREAS.find((candidate) => candidate.id === testCase.area)!;
|
|
77
|
+
const claim = language === "en" ? testCase.claim : testCase.claimZh;
|
|
78
|
+
return `| \`${testCase.path}\` | ${areaTitle(area, language)} | TS${testCase.code} | ${claim} |`;
|
|
79
|
+
});
|
|
80
|
+
return [header, ...rows].join("\n");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function renderSupportMatrix(language: Language): string {
|
|
84
|
+
const corpusLink =
|
|
85
|
+
language === "en" ? "../tests/conformance/test262/manifest.ts" : "../../tests/conformance/test262/manifest.ts";
|
|
86
|
+
const testLink =
|
|
87
|
+
language === "en" ? "../tests/conformance/test262.test.ts" : "../../tests/conformance/test262.test.ts";
|
|
88
|
+
const sourceLink =
|
|
89
|
+
language === "en" ? "../tests/conformance/test262/SOURCE.md" : "../../tests/conformance/test262/SOURCE.md";
|
|
90
|
+
|
|
91
|
+
if (language === "en") {
|
|
92
|
+
return `# Support matrix
|
|
93
|
+
|
|
94
|
+
> Language: **English** | [简体中文](./zh-CN/support-matrix.md)
|
|
95
|
+
|
|
96
|
+
> **Generated** by \`npm run docs:matrix\` from the executable catalogue in
|
|
97
|
+
> [\`tests/conformance/test262/manifest.ts\`](${corpusLink}). Do not edit this
|
|
98
|
+
> file by hand: change a case and regenerate.
|
|
99
|
+
|
|
100
|
+
Every supported case is an unmodified [test262](https://github.com/tc39/test262)
|
|
101
|
+
file (pinned at \`${TEST262_COMMIT}\`) that xbintsc compiles **and runs**; the
|
|
102
|
+
[test262 suite](${testLink}) fails if one stops passing. The corpus is a
|
|
103
|
+
representative subset, not a full test262 run. Every unsupported case
|
|
104
|
+
is valid JavaScript that xbintsc currently rejects, pinned with the diagnostic
|
|
105
|
+
code it produces. See [\`SOURCE.md\`](${sourceLink}) for the harness adaptation.
|
|
106
|
+
Because the suite runs on every CI platform, this table cannot claim more than
|
|
107
|
+
the compiler does.
|
|
108
|
+
|
|
109
|
+
## Coverage by area
|
|
110
|
+
|
|
111
|
+
| Area | Supported | Unsupported | Reference |
|
|
112
|
+
| --- | ---: | ---: | --- |
|
|
113
|
+
${rowsFor(language)}
|
|
114
|
+
|
|
115
|
+
## Supported cases (test262, compiled and executed)
|
|
116
|
+
|
|
117
|
+
${supportedTable(language)}
|
|
118
|
+
|
|
119
|
+
## Unsupported cases (valid JavaScript, expected diagnostics)
|
|
120
|
+
|
|
121
|
+
${unsupportedTable(language)}
|
|
122
|
+
`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return `# 支持矩阵
|
|
126
|
+
|
|
127
|
+
> 语言:[English](../support-matrix.md) | **简体中文**
|
|
128
|
+
|
|
129
|
+
> 本文件由 \`npm run docs:matrix\` 根据可执行语料
|
|
130
|
+
> [\`tests/conformance/test262/manifest.ts\`](${corpusLink}) 生成,请勿手工编辑:
|
|
131
|
+
> 修改用例后重新生成。
|
|
132
|
+
|
|
133
|
+
每个“支持”用例都是 [test262](https://github.com/tc39/test262) 的原始文件
|
|
134
|
+
(固定版本 \`${TEST262_COMMIT}\`),由 xbintsc 编译**并执行**;
|
|
135
|
+
[test262 测试套件](${testLink}) 会在用例回归时失败。该语料是代表性
|
|
136
|
+
子集,不是完整的 test262 全量运行。每个“不支持”用例都是
|
|
137
|
+
xbintsc 目前会拒绝的合法 JavaScript,并以实际产生的诊断码固定下来。
|
|
138
|
+
harness 的适配说明见 [\`SOURCE.md\`](${sourceLink})。该套件在 CI 的每个平台
|
|
139
|
+
运行,因此本表不会声称编译器做不到的能力。
|
|
140
|
+
|
|
141
|
+
## 各领域覆盖
|
|
142
|
+
|
|
143
|
+
| 领域 | 支持 | 不支持 | 参考 |
|
|
144
|
+
| --- | ---: | ---: | --- |
|
|
145
|
+
${rowsFor(language)}
|
|
146
|
+
|
|
147
|
+
## 支持的用例(test262,编译并执行)
|
|
148
|
+
|
|
149
|
+
${supportedTable(language)}
|
|
150
|
+
|
|
151
|
+
## 不支持的用例(合法 JavaScript,预期诊断)
|
|
152
|
+
|
|
153
|
+
${unsupportedTable(language)}
|
|
154
|
+
`;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function main(): void {
|
|
158
|
+
for (const language of ["en", "zh"] as const) {
|
|
159
|
+
const path = resolve(root, MATRIX_FILES[language]);
|
|
160
|
+
writeFileSync(path, renderSupportMatrix(language));
|
|
161
|
+
process.stdout.write(`xbintsc: wrote ${MATRIX_FILES[language]}\n`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (process.argv[1] !== undefined && pathToFileURL(resolve(process.argv[1])).href === import.meta.url) {
|
|
166
|
+
main();
|
|
167
|
+
}
|
package/src/ast/common.ts
CHANGED
|
@@ -33,6 +33,7 @@ import type {
|
|
|
33
33
|
PropertyAccessExpression,
|
|
34
34
|
RegularExpressionLiteral,
|
|
35
35
|
SatisfiesExpression,
|
|
36
|
+
SequenceExpression,
|
|
36
37
|
SpreadElement,
|
|
37
38
|
StringLiteral,
|
|
38
39
|
TaggedTemplateExpression,
|
|
@@ -143,6 +144,7 @@ export type Expression =
|
|
|
143
144
|
| ConditionalExpression
|
|
144
145
|
| AsExpression
|
|
145
146
|
| SatisfiesExpression
|
|
147
|
+
| SequenceExpression
|
|
146
148
|
| NonNullExpression
|
|
147
149
|
| TypeOfExpression
|
|
148
150
|
| VoidExpression
|
package/src/ast/declarations.ts
CHANGED
|
@@ -75,7 +75,11 @@ export interface ExpressionWithTypeArguments extends Node {
|
|
|
75
75
|
readonly typeArguments: TypeNode[];
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
export type ClassElement =
|
|
78
|
+
export type ClassElement =
|
|
79
|
+
| PropertyDeclaration
|
|
80
|
+
| MethodDeclaration
|
|
81
|
+
| ConstructorDeclaration
|
|
82
|
+
| ClassStaticBlockDeclaration;
|
|
79
83
|
|
|
80
84
|
export interface PropertyDeclaration extends Node {
|
|
81
85
|
readonly kind: SyntaxKind.PropertyDeclaration;
|
|
@@ -108,6 +112,13 @@ export interface ConstructorDeclaration extends Node {
|
|
|
108
112
|
readonly body?: Block;
|
|
109
113
|
}
|
|
110
114
|
|
|
115
|
+
/** `static { ... }`: runs once, while the class is being defined. */
|
|
116
|
+
export interface ClassStaticBlockDeclaration extends Node {
|
|
117
|
+
readonly kind: SyntaxKind.ClassStaticBlockDeclaration;
|
|
118
|
+
readonly modifiers: Modifier[];
|
|
119
|
+
readonly body: Block;
|
|
120
|
+
}
|
|
121
|
+
|
|
111
122
|
export interface ClassDeclaration extends Node {
|
|
112
123
|
readonly kind: SyntaxKind.ClassDeclaration;
|
|
113
124
|
readonly name?: Identifier;
|
package/src/ast/expressions.ts
CHANGED
|
@@ -206,6 +206,12 @@ export interface ParenthesizedExpression extends Node {
|
|
|
206
206
|
readonly expression: Expression;
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
+
/** `a, b, c`: evaluates every operand left to right, yields the last value. */
|
|
210
|
+
export interface SequenceExpression extends Node {
|
|
211
|
+
readonly kind: SyntaxKind.SequenceExpression;
|
|
212
|
+
readonly expressions: Expression[];
|
|
213
|
+
}
|
|
214
|
+
|
|
209
215
|
export interface PrefixUnaryExpression extends Node {
|
|
210
216
|
readonly kind: SyntaxKind.PrefixUnaryExpression;
|
|
211
217
|
readonly operator: PrefixUnaryOperator;
|
package/src/ast/kinds.ts
CHANGED
|
@@ -63,6 +63,7 @@ export const enum SyntaxKind {
|
|
|
63
63
|
ObjectBindingPattern = 47,
|
|
64
64
|
BindingElement = 48,
|
|
65
65
|
ComputedPropertyName = 49,
|
|
66
|
+
SequenceExpression = 50,
|
|
66
67
|
|
|
67
68
|
// Statements
|
|
68
69
|
ExpressionStatement = 60,
|
|
@@ -112,6 +113,7 @@ export const enum SyntaxKind {
|
|
|
112
113
|
ExportAssignment = 119,
|
|
113
114
|
NamedExports = 120,
|
|
114
115
|
ExportSpecifier = 121,
|
|
116
|
+
ClassStaticBlockDeclaration = 122,
|
|
115
117
|
|
|
116
118
|
// Types
|
|
117
119
|
TypeReference = 200,
|
package/src/binder/binder.ts
CHANGED
|
@@ -20,6 +20,7 @@ import type { Identifier, Node, SourceFileNode } from "../ast/nodes.js";
|
|
|
20
20
|
import {
|
|
21
21
|
ScopeKind,
|
|
22
22
|
type ClassInfo,
|
|
23
|
+
type DeclarationConflict,
|
|
23
24
|
type FunctionInfo,
|
|
24
25
|
type MutableFunction,
|
|
25
26
|
type Scope,
|
|
@@ -45,6 +46,7 @@ export class Binder {
|
|
|
45
46
|
readonly symbolOfIdentifier = new Map<Identifier, SymbolInfo>();
|
|
46
47
|
readonly scopes = new Map<Node, Scope>();
|
|
47
48
|
readonly unresolved: Identifier[] = [];
|
|
49
|
+
readonly conflicts: DeclarationConflict[] = [];
|
|
48
50
|
nextSymbolId = 1;
|
|
49
51
|
nextFunctionId = 1;
|
|
50
52
|
nextClassId = 1;
|
|
@@ -83,6 +85,7 @@ export class Binder {
|
|
|
83
85
|
symbolOfIdentifier: this.symbolOfIdentifier,
|
|
84
86
|
scopes: this.scopes,
|
|
85
87
|
unresolved: this.unresolved,
|
|
88
|
+
conflicts: this.conflicts,
|
|
86
89
|
};
|
|
87
90
|
}
|
|
88
91
|
|
|
@@ -20,6 +20,71 @@ import { SymbolKind, type MutableFunction, type Scope, type SymbolInfo } from ".
|
|
|
20
20
|
import { childNodes } from "./helpers.js";
|
|
21
21
|
import type { Binder } from "./binder.js";
|
|
22
22
|
|
|
23
|
+
/** Kinds that only introduce a type name, never a runtime binding. */
|
|
24
|
+
const TYPE_ONLY_KINDS: ReadonlySet<SymbolKind> = new Set([
|
|
25
|
+
SymbolKind.Interface,
|
|
26
|
+
SymbolKind.TypeAlias,
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
function isVarLike(kind: SymbolKind): boolean {
|
|
30
|
+
return kind === SymbolKind.Var || kind === SymbolKind.Function;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Whether a declaration of `next` may legally share a scope with `existing`.
|
|
35
|
+
*
|
|
36
|
+
* This is JavaScript's redeclaration rules plus TypeScript's declaration
|
|
37
|
+
* merging, kept deliberately explicit: a wrong `true` would hide a real bug, a
|
|
38
|
+
* wrong `false` would make valid code fail to compile. Only the cases this
|
|
39
|
+
* compiler can actually see are covered; anything unknown is treated as legal.
|
|
40
|
+
*/
|
|
41
|
+
export function declarationsCanMerge(existing: SymbolKind, next: SymbolKind): boolean {
|
|
42
|
+
if (existing === next) {
|
|
43
|
+
/* Repeated `var` / `function` / `interface` / `enum` declarations merge.
|
|
44
|
+
* Two imports may also share a name: bundling merges every module into one
|
|
45
|
+
* scope, and separate modules routinely import the same builtin
|
|
46
|
+
* (`readFileSync` from `node:fs`, `dirname` from `node:path`). The import
|
|
47
|
+
* map is keyed by symbol id, so keeping the first declaration is enough.
|
|
48
|
+
* `let`, `const`, `class` and parameters do not merge. */
|
|
49
|
+
return (
|
|
50
|
+
existing === SymbolKind.Var ||
|
|
51
|
+
existing === SymbolKind.Function ||
|
|
52
|
+
existing === SymbolKind.Interface ||
|
|
53
|
+
existing === SymbolKind.Namespace ||
|
|
54
|
+
existing === SymbolKind.Enum ||
|
|
55
|
+
existing === SymbolKind.Import
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
// `var` and `function` are both function-scoped and may coexist in any order.
|
|
59
|
+
if (isVarLike(existing) && isVarLike(next)) return true;
|
|
60
|
+
// `var` may redeclare a parameter; `let`/`const` may not.
|
|
61
|
+
if (
|
|
62
|
+
(existing === SymbolKind.Parameter && next === SymbolKind.Var) ||
|
|
63
|
+
(existing === SymbolKind.Var && next === SymbolKind.Parameter)
|
|
64
|
+
) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
// Namespaces merge with classes, functions, enums and each other.
|
|
68
|
+
if (existing === SymbolKind.Namespace || next === SymbolKind.Namespace) return true;
|
|
69
|
+
// A class and an interface merge their instance shape.
|
|
70
|
+
if (
|
|
71
|
+
(existing === SymbolKind.Class && next === SymbolKind.Interface) ||
|
|
72
|
+
(existing === SymbolKind.Interface && next === SymbolKind.Class)
|
|
73
|
+
) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
// An import binds both a value and a type name, so it conflicts with any
|
|
77
|
+
// same-name local declaration.
|
|
78
|
+
if (existing === SymbolKind.Import || next === SymbolKind.Import) return false;
|
|
79
|
+
// Value and type names live in separate declaration spaces, except classes
|
|
80
|
+
// and enums, which declare a type as well as a value.
|
|
81
|
+
if (TYPE_ONLY_KINDS.has(existing) !== TYPE_ONLY_KINDS.has(next)) {
|
|
82
|
+
const valueKind = TYPE_ONLY_KINDS.has(existing) ? next : existing;
|
|
83
|
+
return valueKind !== SymbolKind.Class && valueKind !== SymbolKind.Enum;
|
|
84
|
+
}
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
23
88
|
export interface DeclarationMethods {
|
|
24
89
|
declareBinding(this: Binder, name: BindingName, kind: SymbolKind, declaration: Node, scope: Scope, mutable: boolean): SymbolInfo | undefined;
|
|
25
90
|
declare(this: Binder, name: string, kind: SymbolKind, node: Node, scope: Scope, mutable: boolean): SymbolInfo;
|
|
@@ -60,6 +125,11 @@ export const declarationMethods: DeclarationMethods = {
|
|
|
60
125
|
): SymbolInfo {
|
|
61
126
|
const existing = scope.symbols.get(name);
|
|
62
127
|
if (existing) {
|
|
128
|
+
// `(anonymous)` is the binder's placeholder for `export default
|
|
129
|
+
// function () {}`; those have no user-visible name to collide.
|
|
130
|
+
if (name !== "(anonymous)" && !declarationsCanMerge(existing.kind, kind)) {
|
|
131
|
+
this.conflicts.push({ name, existing, kind, node });
|
|
132
|
+
}
|
|
63
133
|
// `var` redeclarations and duplicate functions merge into one symbol.
|
|
64
134
|
if (
|
|
65
135
|
(kind === SymbolKind.Var && existing.kind === SymbolKind.Var) ||
|
package/src/binder/references.ts
CHANGED
|
@@ -33,7 +33,9 @@ import type { ArrayBindingPattern, ObjectBindingPattern, Parameter } from "../as
|
|
|
33
33
|
import {
|
|
34
34
|
ScopeKind,
|
|
35
35
|
SymbolKind,
|
|
36
|
+
type ClassFieldInfo,
|
|
36
37
|
type ClassInfo,
|
|
38
|
+
type ClassStaticInit,
|
|
37
39
|
type FunctionInfo,
|
|
38
40
|
type FunctionNode,
|
|
39
41
|
type MutableFunction,
|
|
@@ -136,6 +138,23 @@ export const referenceMethods: ReferenceMethods = {
|
|
|
136
138
|
case SyntaxKind.LabeledStatement:
|
|
137
139
|
this.bindNode((node as unknown as { statement: Node }).statement, scope);
|
|
138
140
|
return;
|
|
141
|
+
case SyntaxKind.SwitchStatement: {
|
|
142
|
+
const statement = node as unknown as {
|
|
143
|
+
expression: Expression;
|
|
144
|
+
clauses: { expression?: Expression; statements: Statement[] }[];
|
|
145
|
+
};
|
|
146
|
+
this.bindNode(statement.expression, scope);
|
|
147
|
+
/* Every `case` body shares the switch's block scope, so the
|
|
148
|
+
* declarations they contain have to be pre-declared before any clause
|
|
149
|
+
* is bound. Without this a `const` declared directly in a `case`
|
|
150
|
+
* clause had no symbol and later phases crashed on it. */
|
|
151
|
+
for (const clause of statement.clauses) {
|
|
152
|
+
this.bindNode(clause.expression, scope);
|
|
153
|
+
this.predeclareStatements(clause.statements, scope);
|
|
154
|
+
}
|
|
155
|
+
for (const clause of statement.clauses) this.bindStatements(clause.statements, scope);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
139
158
|
case SyntaxKind.BreakStatement:
|
|
140
159
|
case SyntaxKind.ContinueStatement:
|
|
141
160
|
return;
|
|
@@ -150,6 +169,15 @@ export const referenceMethods: ReferenceMethods = {
|
|
|
150
169
|
case SyntaxKind.TypeAliasDeclaration:
|
|
151
170
|
// Type-only: skip the body entirely.
|
|
152
171
|
return;
|
|
172
|
+
case SyntaxKind.EnumDeclaration: {
|
|
173
|
+
/* Member names are keys of the generated object, not bindings; only an
|
|
174
|
+
* initializer (`A = foo()`) contains runtime references. */
|
|
175
|
+
const members = (node as unknown as { members: { initializer?: Expression }[] }).members;
|
|
176
|
+
for (const member of members) {
|
|
177
|
+
if (member.initializer) this.bindNode(member.initializer, scope);
|
|
178
|
+
}
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
153
181
|
case SyntaxKind.ImportDeclaration:
|
|
154
182
|
return;
|
|
155
183
|
case SyntaxKind.ExportDeclaration: {
|
|
@@ -204,6 +232,22 @@ export const referenceMethods: ReferenceMethods = {
|
|
|
204
232
|
this.bindBlock(clause.block, catchScope);
|
|
205
233
|
return;
|
|
206
234
|
}
|
|
235
|
+
/* Type positions are erased, so their identifiers are not runtime
|
|
236
|
+
* references. Walking them would put `Foo` from `x as Foo` or the type
|
|
237
|
+
* arguments of `f<Foo>()` into `unresolved`, and the checker would then
|
|
238
|
+
* report a value that never exists. */
|
|
239
|
+
case SyntaxKind.AsExpression:
|
|
240
|
+
case SyntaxKind.SatisfiesExpression:
|
|
241
|
+
case SyntaxKind.NonNullExpression:
|
|
242
|
+
this.bindNode((node as unknown as { expression: Expression }).expression, scope);
|
|
243
|
+
return;
|
|
244
|
+
case SyntaxKind.CallExpression:
|
|
245
|
+
case SyntaxKind.NewExpression: {
|
|
246
|
+
const call = node as unknown as { expression: Expression; arguments: Expression[] };
|
|
247
|
+
this.bindNode(call.expression, scope);
|
|
248
|
+
for (const argument of call.arguments) this.bindNode(argument, scope);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
207
251
|
default:
|
|
208
252
|
break;
|
|
209
253
|
}
|
|
@@ -211,10 +255,24 @@ export const referenceMethods: ReferenceMethods = {
|
|
|
211
255
|
},
|
|
212
256
|
|
|
213
257
|
bindVariableList(list: VariableDeclarationList, scope: Scope): void {
|
|
258
|
+
const declarationKind =
|
|
259
|
+
list.declarationKind === "const"
|
|
260
|
+
? SymbolKind.Const
|
|
261
|
+
: list.declarationKind === "var"
|
|
262
|
+
? SymbolKind.Var
|
|
263
|
+
: SymbolKind.Let;
|
|
214
264
|
for (const declaration of list.declarations) {
|
|
215
|
-
const symbol = this.symbolOfDeclaration.get(declaration);
|
|
216
265
|
if (declaration.name.kind === SyntaxKind.Identifier) {
|
|
217
|
-
|
|
266
|
+
/* Normally the declaration was pre-declared; if it was not (a code
|
|
267
|
+
* path that binds statements without pre-declaring them), declare it
|
|
268
|
+
* here rather than storing an empty entry that later phases would
|
|
269
|
+
* dereference. */
|
|
270
|
+
const name = declaration.name as Identifier;
|
|
271
|
+
const symbol =
|
|
272
|
+
this.symbolOfDeclaration.get(declaration) ??
|
|
273
|
+
this.symbolOfDeclaration.get(name) ??
|
|
274
|
+
this.declareBinding(name, declarationKind, declaration, scope, declarationKind !== SymbolKind.Const);
|
|
275
|
+
if (symbol) this.symbolOfDeclaration.set(name, symbol);
|
|
218
276
|
} else {
|
|
219
277
|
this.bindBindingPattern(declaration.name, scope);
|
|
220
278
|
}
|
|
@@ -329,6 +387,8 @@ export const referenceMethods: ReferenceMethods = {
|
|
|
329
387
|
fields: [],
|
|
330
388
|
methods: [],
|
|
331
389
|
statics: [],
|
|
390
|
+
staticBlocks: [],
|
|
391
|
+
staticInit: [],
|
|
332
392
|
};
|
|
333
393
|
this.classes.push(info);
|
|
334
394
|
this.classOfNode.set(node, info);
|
|
@@ -337,6 +397,9 @@ export const referenceMethods: ReferenceMethods = {
|
|
|
337
397
|
this.scopes.set(node, classScope);
|
|
338
398
|
|
|
339
399
|
let constructor: FunctionInfo | undefined;
|
|
400
|
+
/* `static { ... }` functions, so the field pass below can interleave them
|
|
401
|
+
* with static fields in declaration order. */
|
|
402
|
+
const staticBlockFns = new Map<Node, FunctionInfo>();
|
|
340
403
|
for (const member of node.members) {
|
|
341
404
|
if (member.kind === SyntaxKind.ConstructorDeclaration) {
|
|
342
405
|
const ctor = member as ConstructorDeclaration;
|
|
@@ -354,6 +417,14 @@ export const referenceMethods: ReferenceMethods = {
|
|
|
354
417
|
}
|
|
355
418
|
if (isStatic) (info.statics as FunctionInfo[]).push(fn);
|
|
356
419
|
else (info.methods as FunctionInfo[]).push(fn);
|
|
420
|
+
} else if (member.kind === SyntaxKind.ClassStaticBlockDeclaration) {
|
|
421
|
+
/* A static block is a function-like body: it runs once with `this`
|
|
422
|
+
* bound to the class, so it is bound like a static method and called
|
|
423
|
+
* right after the class value is built. */
|
|
424
|
+
const block = member as unknown as { body: Block };
|
|
425
|
+
const fn = this.createClassFunction(member, "static", [], block.body, classScope, info, true, false);
|
|
426
|
+
(info.staticBlocks as FunctionInfo[]).push(fn);
|
|
427
|
+
staticBlockFns.set(member, fn);
|
|
357
428
|
}
|
|
358
429
|
}
|
|
359
430
|
if (!constructor) {
|
|
@@ -371,7 +442,17 @@ export const referenceMethods: ReferenceMethods = {
|
|
|
371
442
|
this.current = constructor as MutableFunction;
|
|
372
443
|
if (property.initializer) this.bindNode(property.initializer, classScope);
|
|
373
444
|
this.current = owner;
|
|
374
|
-
|
|
445
|
+
const field: ClassFieldInfo = {
|
|
446
|
+
name: classMemberName(property.name),
|
|
447
|
+
initializer: property.initializer,
|
|
448
|
+
fn: constructor,
|
|
449
|
+
isStatic,
|
|
450
|
+
};
|
|
451
|
+
(info.fields as ClassFieldInfo[]).push(field);
|
|
452
|
+
if (isStatic) (info.staticInit as ClassStaticInit[]).push({ kind: "field", field });
|
|
453
|
+
} else if (member.kind === SyntaxKind.ClassStaticBlockDeclaration) {
|
|
454
|
+
const fn = staticBlockFns.get(member);
|
|
455
|
+
if (fn) (info.staticInit as ClassStaticInit[]).push({ kind: "block", fn });
|
|
375
456
|
}
|
|
376
457
|
}
|
|
377
458
|
|
package/src/binder/types.ts
CHANGED
|
@@ -43,6 +43,24 @@ export interface SymbolInfo {
|
|
|
43
43
|
boxed: boolean;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* A same-scope declaration that cannot legally merge with the symbol already
|
|
48
|
+
* bound to that name (`let x` twice, `function f` then `const f`, ...).
|
|
49
|
+
*
|
|
50
|
+
* The binder records the conflict instead of reporting it: whether it is an
|
|
51
|
+
* error is checker policy (`--no-check` keeps the old, permissive behaviour),
|
|
52
|
+
* while the fact itself is cheap to capture during the one declaration pass.
|
|
53
|
+
*/
|
|
54
|
+
export interface DeclarationConflict {
|
|
55
|
+
readonly name: string;
|
|
56
|
+
/** The symbol the name was already bound to. */
|
|
57
|
+
readonly existing: SymbolInfo;
|
|
58
|
+
/** The kind of the offending declaration. */
|
|
59
|
+
readonly kind: SymbolKind;
|
|
60
|
+
/** The offending declaration node (the second one to use the name). */
|
|
61
|
+
readonly node: Node;
|
|
62
|
+
}
|
|
63
|
+
|
|
46
64
|
export type FunctionNode = SourceFileNode | FunctionDeclaration | FunctionExpression | ArrowFunction;
|
|
47
65
|
|
|
48
66
|
export interface FunctionInfo {
|
|
@@ -88,10 +106,20 @@ export interface ClassInfo {
|
|
|
88
106
|
readonly fields: ClassFieldInfo[];
|
|
89
107
|
readonly methods: FunctionInfo[];
|
|
90
108
|
readonly statics: FunctionInfo[];
|
|
109
|
+
/** `static { ... }` blocks, in declaration order. */
|
|
110
|
+
readonly staticBlocks: FunctionInfo[];
|
|
111
|
+
/** Static fields and static blocks, interleaved in declaration order: they
|
|
112
|
+
* run in source order, while static methods are installed before both. */
|
|
113
|
+
readonly staticInit: ClassStaticInit[];
|
|
91
114
|
ctor?: FunctionInfo;
|
|
92
115
|
/** The symbol the class name binds to, when there is one. */
|
|
93
116
|
}
|
|
94
117
|
|
|
118
|
+
/** One static element evaluated at class-definition time, in source order. */
|
|
119
|
+
export type ClassStaticInit =
|
|
120
|
+
| { readonly kind: "field"; readonly field: ClassFieldInfo }
|
|
121
|
+
| { readonly kind: "block"; readonly fn: FunctionInfo };
|
|
122
|
+
|
|
95
123
|
export interface ClassFieldInfo {
|
|
96
124
|
readonly name: string;
|
|
97
125
|
readonly initializer: Expression | undefined;
|
|
@@ -129,6 +157,8 @@ export interface BindResult {
|
|
|
129
157
|
readonly scopes: Map<Node, Scope>;
|
|
130
158
|
/** Identifier references that could not be resolved in user code. */
|
|
131
159
|
readonly unresolved: Identifier[];
|
|
160
|
+
/** Same-scope declarations that cannot merge (see {@link DeclarationConflict}). */
|
|
161
|
+
readonly conflicts: readonly DeclarationConflict[];
|
|
132
162
|
}
|
|
133
163
|
|
|
134
164
|
export interface MutableFunction extends FunctionInfo {
|
package/src/canonical.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical bytes for compiler-emitted artifacts.
|
|
3
|
+
*
|
|
4
|
+
* The compiler runs on Windows, macOS and Linux, and can be compiled by
|
|
5
|
+
* itself. Anything it writes into a byte-compared artifact — LLVM IR, debug
|
|
6
|
+
* metadata, the compiler fingerprint, the bundled module text and the `path`
|
|
7
|
+
* module's results — has to use the same representation on every host. These
|
|
8
|
+
* constants are that representation: do not spell `"/"` or `"\n"` in code that
|
|
9
|
+
* emits an artifact.
|
|
10
|
+
*
|
|
11
|
+
* Native paths are deliberately different. Diagnostics, `import.meta.filename`
|
|
12
|
+
* and `process.cwd()` keep the host separator, exactly like Node. Convert a
|
|
13
|
+
* native path with {@link artifactPath} only when it enters an artifact.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** Separator between path segments in a compiler artifact. Deliberately not
|
|
17
|
+
* selected by `process.platform`: every host writes `/`, so the same source
|
|
18
|
+
* produces the same bytes (and Windows accepts `/` in every API). */
|
|
19
|
+
export const ARTIFACT_PATH_SEPARATOR = "/";
|
|
20
|
+
|
|
21
|
+
/** Line ending between records in a compiler artifact. Deliberately not
|
|
22
|
+
* `os.EOL`/`"\r\n"` on Windows: the runtime opens stdout/stderr in binary
|
|
23
|
+
* mode, and CRLF would make IR, fingerprints and documentation differ per
|
|
24
|
+
* host. */
|
|
25
|
+
export const ARTIFACT_LINE_ENDING = "\n";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Rewrite a native path for an artifact: `C:\dir\file.ts` becomes
|
|
29
|
+
* `C:/dir/file.ts`. A backslash is always a separator here, matching how the
|
|
30
|
+
* runtime and Node treat Windows paths.
|
|
31
|
+
*/
|
|
32
|
+
export function artifactPath(path: string): string {
|
|
33
|
+
// `split`/`join` is measurably faster than a regex or `replaceAll` for the
|
|
34
|
+
// short paths this sees (it runs once per emitted stack frame), and it is the
|
|
35
|
+
// exact transform the compiler used before it was centralised.
|
|
36
|
+
return path.split("\\").join(ARTIFACT_PATH_SEPARATOR);
|
|
37
|
+
}
|