@soundscript/soundscript 0.1.13 → 0.1.15
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/package.json +15 -6
- package/project-transform/index.js +2 -0
- package/project-transform/index.ts +8 -0
- package/project-transform/src/annotation_syntax.js +948 -0
- package/project-transform/src/annotation_syntax.ts +1217 -0
- package/project-transform/src/build_package.js +475 -0
- package/project-transform/src/build_package.ts +683 -0
- package/project-transform/src/bundled/portable-web-globals.d.ts +153 -0
- package/project-transform/src/bundled/runtime_externs.js +220 -0
- package/project-transform/src/bundled/runtime_externs.ts +237 -0
- package/project-transform/src/bundled/sound-libs/lib.decorators.d.ts +385 -0
- package/project-transform/src/bundled/sound-libs/lib.decorators.legacy.d.ts +22 -0
- package/project-transform/src/bundled/sound-libs/lib.dom.asynciterable.d.ts +42 -0
- package/project-transform/src/bundled/sound-libs/lib.dom.d.ts +39440 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.collection.d.ts +149 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.core.d.ts +657 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.d.ts +28 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.generator.d.ts +77 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.iterable.d.ts +616 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.promise.d.ts +80 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.proxy.d.ts +128 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.reflect.d.ts +144 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.symbol.d.ts +46 -0
- package/project-transform/src/bundled/sound-libs/lib.es2015.symbol.wellknown.d.ts +170 -0
- package/project-transform/src/bundled/sound-libs/lib.es2016.array.include.d.ts +116 -0
- package/project-transform/src/bundled/sound-libs/lib.es2016.d.ts +21 -0
- package/project-transform/src/bundled/sound-libs/lib.es2017.arraybuffer.d.ts +21 -0
- package/project-transform/src/bundled/sound-libs/lib.es2017.d.ts +26 -0
- package/project-transform/src/bundled/sound-libs/lib.es2017.date.d.ts +31 -0
- package/project-transform/src/bundled/sound-libs/lib.es2017.object.d.ts +49 -0
- package/project-transform/src/bundled/sound-libs/lib.es2017.string.d.ts +45 -0
- package/project-transform/src/bundled/sound-libs/lib.es2017.typedarrays.d.ts +53 -0
- package/project-transform/src/bundled/sound-libs/lib.es2018.asyncgenerator.d.ts +77 -0
- package/project-transform/src/bundled/sound-libs/lib.es2018.asynciterable.d.ts +57 -0
- package/project-transform/src/bundled/sound-libs/lib.es2018.d.ts +24 -0
- package/project-transform/src/bundled/sound-libs/lib.es2018.promise.d.ts +30 -0
- package/project-transform/src/bundled/sound-libs/lib.es2018.regexp.d.ts +37 -0
- package/project-transform/src/bundled/sound-libs/lib.es2019.array.d.ts +79 -0
- package/project-transform/src/bundled/sound-libs/lib.es2019.d.ts +24 -0
- package/project-transform/src/bundled/sound-libs/lib.es2019.object.d.ts +47 -0
- package/project-transform/src/bundled/sound-libs/lib.es2019.string.d.ts +37 -0
- package/project-transform/src/bundled/sound-libs/lib.es2019.symbol.d.ts +24 -0
- package/project-transform/src/bundled/sound-libs/lib.es2020.bigint.d.ts +765 -0
- package/project-transform/src/bundled/sound-libs/lib.es2020.d.ts +27 -0
- package/project-transform/src/bundled/sound-libs/lib.es2020.date.d.ts +42 -0
- package/project-transform/src/bundled/sound-libs/lib.es2020.number.d.ts +28 -0
- package/project-transform/src/bundled/sound-libs/lib.es2020.promise.d.ts +49 -0
- package/project-transform/src/bundled/sound-libs/lib.es2020.string.d.ts +44 -0
- package/project-transform/src/bundled/sound-libs/lib.es2020.symbol.wellknown.d.ts +41 -0
- package/project-transform/src/bundled/sound-libs/lib.es2021.d.ts +23 -0
- package/project-transform/src/bundled/sound-libs/lib.es2021.promise.d.ts +48 -0
- package/project-transform/src/bundled/sound-libs/lib.es2021.string.d.ts +33 -0
- package/project-transform/src/bundled/sound-libs/lib.es2021.weakref.d.ts +78 -0
- package/project-transform/src/bundled/sound-libs/lib.es2022.array.d.ts +121 -0
- package/project-transform/src/bundled/sound-libs/lib.es2022.d.ts +25 -0
- package/project-transform/src/bundled/sound-libs/lib.es2022.error.d.ts +75 -0
- package/project-transform/src/bundled/sound-libs/lib.es2022.object.d.ts +26 -0
- package/project-transform/src/bundled/sound-libs/lib.es2022.regexp.d.ts +39 -0
- package/project-transform/src/bundled/sound-libs/lib.es2022.string.d.ts +25 -0
- package/project-transform/src/bundled/sound-libs/lib.es2023.array.d.ts +924 -0
- package/project-transform/src/bundled/sound-libs/lib.es2023.collection.d.ts +21 -0
- package/project-transform/src/bundled/sound-libs/lib.es2023.d.ts +22 -0
- package/project-transform/src/bundled/sound-libs/lib.es2024.arraybuffer.d.ts +65 -0
- package/project-transform/src/bundled/sound-libs/lib.es2024.collection.d.ts +29 -0
- package/project-transform/src/bundled/sound-libs/lib.es2024.d.ts +26 -0
- package/project-transform/src/bundled/sound-libs/lib.es2024.object.d.ts +33 -0
- package/project-transform/src/bundled/sound-libs/lib.es2024.promise.d.ts +35 -0
- package/project-transform/src/bundled/sound-libs/lib.es2024.regexp.d.ts +25 -0
- package/project-transform/src/bundled/sound-libs/lib.es2024.string.d.ts +29 -0
- package/project-transform/src/bundled/sound-libs/lib.es5.d.ts +4924 -0
- package/project-transform/src/bundled/sound_stdlib.js +142 -0
- package/project-transform/src/bundled/sound_stdlib.ts +180 -0
- package/project-transform/src/checker/analyze_project.js +1361 -0
- package/project-transform/src/checker/analyze_project.ts +2246 -0
- package/project-transform/src/checker/diagnostics.js +112 -0
- package/project-transform/src/checker/diagnostics.ts +222 -0
- package/project-transform/src/checker/engine/context.js +235 -0
- package/project-transform/src/checker/engine/context.ts +340 -0
- package/project-transform/src/checker/engine/diagnostic_codes.js +72 -0
- package/project-transform/src/checker/engine/diagnostic_codes.ts +95 -0
- package/project-transform/src/checker/engine/facts.js +35 -0
- package/project-transform/src/checker/engine/facts.ts +48 -0
- package/project-transform/src/checker/engine/types.js +1 -0
- package/project-transform/src/checker/engine/types.ts +485 -0
- package/project-transform/src/checker/proof_escape_hatch_diagnostics.js +104 -0
- package/project-transform/src/checker/proof_escape_hatch_diagnostics.ts +173 -0
- package/project-transform/src/checker/rules/async_surface.js +231 -0
- package/project-transform/src/checker/rules/async_surface.ts +335 -0
- package/project-transform/src/checker/rules/class_lifecycle.js +798 -0
- package/project-transform/src/checker/rules/class_lifecycle.ts +1276 -0
- package/project-transform/src/checker/rules/directive_validation.js +571 -0
- package/project-transform/src/checker/rules/directive_validation.ts +938 -0
- package/project-transform/src/checker/rules/directives.js +23 -0
- package/project-transform/src/checker/rules/directives.ts +25 -0
- package/project-transform/src/checker/rules/flow.js +202 -0
- package/project-transform/src/checker/rules/flow.ts +333 -0
- package/project-transform/src/checker/rules/flow_facts.js +601 -0
- package/project-transform/src/checker/rules/flow_facts.ts +978 -0
- package/project-transform/src/checker/rules/flow_invalidation.js +1119 -0
- package/project-transform/src/checker/rules/flow_invalidation.ts +2150 -0
- package/project-transform/src/checker/rules/flow_shared.js +2822 -0
- package/project-transform/src/checker/rules/flow_shared.ts +4383 -0
- package/project-transform/src/checker/rules/foreign_boundary.js +120 -0
- package/project-transform/src/checker/rules/foreign_boundary.ts +196 -0
- package/project-transform/src/checker/rules/foreign_projection.js +279 -0
- package/project-transform/src/checker/rules/foreign_projection.ts +425 -0
- package/project-transform/src/checker/rules/generated_helpers.js +13 -0
- package/project-transform/src/checker/rules/generated_helpers.ts +18 -0
- package/project-transform/src/checker/rules/index.js +35 -0
- package/project-transform/src/checker/rules/index.ts +49 -0
- package/project-transform/src/checker/rules/namespace_object.js +845 -0
- package/project-transform/src/checker/rules/namespace_object.ts +1224 -0
- package/project-transform/src/checker/rules/non_ordinary_recovery.js +1328 -0
- package/project-transform/src/checker/rules/non_ordinary_recovery.ts +2391 -0
- package/project-transform/src/checker/rules/null_prototype.js +3 -0
- package/project-transform/src/checker/rules/null_prototype.ts +6 -0
- package/project-transform/src/checker/rules/overloads.js +181 -0
- package/project-transform/src/checker/rules/overloads.ts +317 -0
- package/project-transform/src/checker/rules/predicate_verification.js +691 -0
- package/project-transform/src/checker/rules/predicate_verification.ts +1088 -0
- package/project-transform/src/checker/rules/prototype_hardening.js +237 -0
- package/project-transform/src/checker/rules/prototype_hardening.ts +343 -0
- package/project-transform/src/checker/rules/receiver_discipline.js +263 -0
- package/project-transform/src/checker/rules/receiver_discipline.ts +356 -0
- package/project-transform/src/checker/rules/relations.js +6861 -0
- package/project-transform/src/checker/rules/relations.ts +12158 -0
- package/project-transform/src/checker/rules/resolved_builtins.js +274 -0
- package/project-transform/src/checker/rules/resolved_builtins.ts +438 -0
- package/project-transform/src/checker/rules/trust.js +217 -0
- package/project-transform/src/checker/rules/trust.ts +301 -0
- package/project-transform/src/checker/rules/type_guards.js +173 -0
- package/project-transform/src/checker/rules/type_guards.ts +257 -0
- package/project-transform/src/checker/rules/universal.js +17 -0
- package/project-transform/src/checker/rules/universal.ts +22 -0
- package/project-transform/src/checker/rules/unsafe_value_origin.js +80 -0
- package/project-transform/src/checker/rules/unsafe_value_origin.ts +125 -0
- package/project-transform/src/checker/rules/unsound_imports.js +218 -0
- package/project-transform/src/checker/rules/unsound_imports.ts +301 -0
- package/project-transform/src/checker/rules/unsound_syntax.js +1695 -0
- package/project-transform/src/checker/rules/unsound_syntax.ts +2540 -0
- package/project-transform/src/checker/rules/value_types.js +206 -0
- package/project-transform/src/checker/rules/value_types.ts +407 -0
- package/project-transform/src/checker/timing.js +43 -0
- package/project-transform/src/checker/timing.ts +78 -0
- package/project-transform/src/checker/unsupported_feature_messages.js +337 -0
- package/project-transform/src/checker/unsupported_feature_messages.ts +531 -0
- package/project-transform/src/cli.js +892 -0
- package/project-transform/src/cli.ts +1476 -0
- package/project-transform/src/compiler/compile_project.js +319 -0
- package/project-transform/src/compiler/compile_project.ts +508 -0
- package/project-transform/src/compiler/errors.js +10 -0
- package/project-transform/src/compiler/errors.ts +29 -0
- package/project-transform/src/compiler/ir.js +1 -0
- package/project-transform/src/compiler/ir.ts +1526 -0
- package/project-transform/src/compiler/lower.js +30550 -0
- package/project-transform/src/compiler/lower.ts +43645 -0
- package/project-transform/src/compiler/lower_arrays.js +140 -0
- package/project-transform/src/compiler/lower_arrays.ts +190 -0
- package/project-transform/src/compiler/lower_strings.js +121 -0
- package/project-transform/src/compiler/lower_strings.ts +198 -0
- package/project-transform/src/compiler/lower_tagged.js +329 -0
- package/project-transform/src/compiler/lower_tagged.ts +427 -0
- package/project-transform/src/compiler/lower_views.js +171 -0
- package/project-transform/src/compiler/lower_views.ts +251 -0
- package/project-transform/src/compiler/object_keys.js +25 -0
- package/project-transform/src/compiler/object_keys.ts +35 -0
- package/project-transform/src/compiler/runtime_ir.js +30 -0
- package/project-transform/src/compiler/runtime_ir.ts +727 -0
- package/project-transform/src/compiler/tagged_boundary.js +18 -0
- package/project-transform/src/compiler/tagged_boundary.ts +37 -0
- package/project-transform/src/compiler/toolchain.js +170 -0
- package/project-transform/src/compiler/toolchain.ts +229 -0
- package/project-transform/src/compiler/unicode_case_data.js +2102 -0
- package/project-transform/src/compiler/unicode_case_data.ts +2112 -0
- package/project-transform/src/compiler/wasm_js_host_runtime.js +656 -0
- package/project-transform/src/compiler/wasm_js_host_runtime.ts +762 -0
- package/project-transform/src/compiler/wat_arrays.js +3132 -0
- package/project-transform/src/compiler/wat_arrays.ts +3768 -0
- package/project-transform/src/compiler/wat_emitter.js +17952 -0
- package/project-transform/src/compiler/wat_emitter.ts +22812 -0
- package/project-transform/src/compiler/wat_strings.js +129 -0
- package/project-transform/src/compiler/wat_strings.ts +187 -0
- package/project-transform/src/compiler/wat_tagged.js +548 -0
- package/project-transform/src/compiler/wat_tagged.ts +674 -0
- package/project-transform/src/compiler_generator_runner.js +153 -0
- package/project-transform/src/compiler_generator_runner.ts +171 -0
- package/project-transform/src/compiler_object_test_helpers.js +69 -0
- package/project-transform/src/compiler_object_test_helpers.ts +96 -0
- package/project-transform/src/compiler_promise_runner.js +2116 -0
- package/project-transform/src/compiler_promise_runner.ts +2184 -0
- package/project-transform/src/compiler_test_helpers.js +854 -0
- package/project-transform/src/compiler_test_helpers.ts +1087 -0
- package/project-transform/src/config.js +568 -0
- package/project-transform/src/config.ts +892 -0
- package/project-transform/src/diagnostic_metadata.js +67 -0
- package/project-transform/src/diagnostic_metadata.ts +99 -0
- package/project-transform/src/diagnostic_reference.js +1368 -0
- package/project-transform/src/diagnostic_reference.ts +1523 -0
- package/project-transform/src/editor_diagnostics_worker.js +176 -0
- package/project-transform/src/editor_diagnostics_worker.ts +250 -0
- package/project-transform/src/editor_projection.js +224 -0
- package/project-transform/src/editor_projection.ts +421 -0
- package/project-transform/src/frontend/builtin_expanded_program_test_cleanup.js +47 -0
- package/project-transform/src/frontend/builtin_expanded_program_test_cleanup.ts +72 -0
- package/project-transform/src/frontend/builtin_macro_support.js +842 -0
- package/project-transform/src/frontend/builtin_macro_support.ts +1386 -0
- package/project-transform/src/frontend/builtin_macros.js +409 -0
- package/project-transform/src/frontend/builtin_macros.ts +542 -0
- package/project-transform/src/frontend/component_poc_runtime.js +279 -0
- package/project-transform/src/frontend/component_poc_runtime.ts +372 -0
- package/project-transform/src/frontend/css_macro.js +148 -0
- package/project-transform/src/frontend/css_macro.ts +222 -0
- package/project-transform/src/frontend/derive_macros.js +2072 -0
- package/project-transform/src/frontend/derive_macros.ts +3188 -0
- package/project-transform/src/frontend/embedded_fragment_support.js +106 -0
- package/project-transform/src/frontend/embedded_fragment_support.ts +172 -0
- package/project-transform/src/frontend/error_normalization.js +403 -0
- package/project-transform/src/frontend/error_normalization.ts +832 -0
- package/project-transform/src/frontend/error_stdlib_support.js +1 -0
- package/project-transform/src/frontend/error_stdlib_support.ts +6 -0
- package/project-transform/src/frontend/expand_project.js +169 -0
- package/project-transform/src/frontend/expand_project.ts +248 -0
- package/project-transform/src/frontend/format_soundscript.js +297 -0
- package/project-transform/src/frontend/format_soundscript.ts +582 -0
- package/project-transform/src/frontend/graphql_macro.js +174 -0
- package/project-transform/src/frontend/graphql_macro.ts +253 -0
- package/project-transform/src/frontend/hash_context.js +83 -0
- package/project-transform/src/frontend/hash_context.ts +113 -0
- package/project-transform/src/frontend/hkt_macro.js +448 -0
- package/project-transform/src/frontend/hkt_macro.ts +897 -0
- package/project-transform/src/frontend/import_binding_usage.js +190 -0
- package/project-transform/src/frontend/import_binding_usage.ts +277 -0
- package/project-transform/src/frontend/macro_advanced_backend_adapter.js +58 -0
- package/project-transform/src/frontend/macro_advanced_backend_adapter.ts +123 -0
- package/project-transform/src/frontend/macro_advanced_context.js +826 -0
- package/project-transform/src/frontend/macro_advanced_context.ts +1102 -0
- package/project-transform/src/frontend/macro_advanced_output.js +21 -0
- package/project-transform/src/frontend/macro_advanced_output.ts +41 -0
- package/project-transform/src/frontend/macro_api.js +353 -0
- package/project-transform/src/frontend/macro_api.ts +1722 -0
- package/project-transform/src/frontend/macro_api_internal.js +35 -0
- package/project-transform/src/frontend/macro_api_internal.ts +80 -0
- package/project-transform/src/frontend/macro_api_module_support.js +39 -0
- package/project-transform/src/frontend/macro_api_module_support.ts +65 -0
- package/project-transform/src/frontend/macro_backend_adapter.js +272 -0
- package/project-transform/src/frontend/macro_backend_adapter.ts +420 -0
- package/project-transform/src/frontend/macro_context.js +816 -0
- package/project-transform/src/frontend/macro_context.ts +1105 -0
- package/project-transform/src/frontend/macro_debug.js +99 -0
- package/project-transform/src/frontend/macro_debug.ts +157 -0
- package/project-transform/src/frontend/macro_definition_support.js +28 -0
- package/project-transform/src/frontend/macro_definition_support.ts +73 -0
- package/project-transform/src/frontend/macro_errors.js +40 -0
- package/project-transform/src/frontend/macro_errors.ts +70 -0
- package/project-transform/src/frontend/macro_expander.js +919 -0
- package/project-transform/src/frontend/macro_expander.ts +1611 -0
- package/project-transform/src/frontend/macro_factory_support.js +176 -0
- package/project-transform/src/frontend/macro_factory_support.ts +263 -0
- package/project-transform/src/frontend/macro_host_ast_internal.js +64 -0
- package/project-transform/src/frontend/macro_host_ast_internal.ts +109 -0
- package/project-transform/src/frontend/macro_index.js +27 -0
- package/project-transform/src/frontend/macro_index.ts +50 -0
- package/project-transform/src/frontend/macro_loader.js +281 -0
- package/project-transform/src/frontend/macro_loader.ts +506 -0
- package/project-transform/src/frontend/macro_operand_semantics.js +838 -0
- package/project-transform/src/frontend/macro_operand_semantics.ts +1489 -0
- package/project-transform/src/frontend/macro_output.js +54 -0
- package/project-transform/src/frontend/macro_output.ts +123 -0
- package/project-transform/src/frontend/macro_parser.js +611 -0
- package/project-transform/src/frontend/macro_parser.ts +832 -0
- package/project-transform/src/frontend/macro_resolver.js +69 -0
- package/project-transform/src/frontend/macro_resolver.ts +125 -0
- package/project-transform/src/frontend/macro_rewrite.js +285 -0
- package/project-transform/src/frontend/macro_rewrite.ts +442 -0
- package/project-transform/src/frontend/macro_runtime_support.js +232 -0
- package/project-transform/src/frontend/macro_runtime_support.ts +324 -0
- package/project-transform/src/frontend/macro_scanner.js +393 -0
- package/project-transform/src/frontend/macro_scanner.ts +455 -0
- package/project-transform/src/frontend/macro_semantic_backend_adapter.js +87 -0
- package/project-transform/src/frontend/macro_semantic_backend_adapter.ts +166 -0
- package/project-transform/src/frontend/macro_semantic_context.js +5 -0
- package/project-transform/src/frontend/macro_semantic_context.ts +12 -0
- package/project-transform/src/frontend/macro_semantic_output.js +24 -0
- package/project-transform/src/frontend/macro_semantic_output.ts +47 -0
- package/project-transform/src/frontend/macro_semantic_types.js +1 -0
- package/project-transform/src/frontend/macro_semantic_types.ts +98 -0
- package/project-transform/src/frontend/macro_semantics.js +1172 -0
- package/project-transform/src/frontend/macro_semantics.ts +1502 -0
- package/project-transform/src/frontend/macro_site_kind_support.js +164 -0
- package/project-transform/src/frontend/macro_site_kind_support.ts +255 -0
- package/project-transform/src/frontend/macro_syntax_internal.js +1950 -0
- package/project-transform/src/frontend/macro_syntax_internal.ts +3338 -0
- package/project-transform/src/frontend/macro_templates.js +57 -0
- package/project-transform/src/frontend/macro_templates.ts +143 -0
- package/project-transform/src/frontend/macro_test_helpers.js +82 -0
- package/project-transform/src/frontend/macro_test_helpers.ts +136 -0
- package/project-transform/src/frontend/macro_types.js +1 -0
- package/project-transform/src/frontend/macro_types.ts +103 -0
- package/project-transform/src/frontend/macro_vm.js +39 -0
- package/project-transform/src/frontend/macro_vm.ts +113 -0
- package/project-transform/src/frontend/match_macro.js +885 -0
- package/project-transform/src/frontend/match_macro.ts +1220 -0
- package/project-transform/src/frontend/numeric_normalization.js +824 -0
- package/project-transform/src/frontend/numeric_normalization.ts +1380 -0
- package/project-transform/src/frontend/numeric_prelude.js +278 -0
- package/project-transform/src/frontend/numeric_prelude.ts +370 -0
- package/project-transform/src/frontend/project_frontend.js +2396 -0
- package/project-transform/src/frontend/project_frontend.ts +3776 -0
- package/project-transform/src/frontend/project_macro_support.js +1401 -0
- package/project-transform/src/frontend/project_macro_support.ts +2137 -0
- package/project-transform/src/frontend/sql_macro.js +175 -0
- package/project-transform/src/frontend/sql_macro.ts +254 -0
- package/project-transform/src/frontend/sql_stdlib_support.js +1 -0
- package/project-transform/src/frontend/sql_stdlib_support.ts +6 -0
- package/project-transform/src/frontend/std_package_support.js +228 -0
- package/project-transform/src/frontend/std_package_support.ts +400 -0
- package/project-transform/src/frontend/value_normalization.js +306 -0
- package/project-transform/src/frontend/value_normalization.ts +599 -0
- package/project-transform/src/lsp/project_service.js +4771 -0
- package/project-transform/src/lsp/project_service.ts +7580 -0
- package/project-transform/src/lsp/protocol.js +9 -0
- package/project-transform/src/lsp/protocol.ts +38 -0
- package/project-transform/src/lsp/server.js +355 -0
- package/project-transform/src/lsp/server.ts +671 -0
- package/project-transform/src/lsp/session.js +49 -0
- package/project-transform/src/lsp/session.ts +48 -0
- package/project-transform/src/lsp/timing.js +43 -0
- package/project-transform/src/lsp/timing.ts +76 -0
- package/project-transform/src/lsp/transport.js +205 -0
- package/project-transform/src/lsp/transport.ts +253 -0
- package/project-transform/src/lsp_main.js +5 -0
- package/project-transform/src/lsp_main.ts +7 -0
- package/project-transform/src/macros.d.ts +1 -0
- package/project-transform/src/macros.js +1 -0
- package/project-transform/src/macros.ts +1 -0
- package/project-transform/src/main.js +24 -0
- package/project-transform/src/main.ts +28 -0
- package/project-transform/src/platform/host.js +264 -0
- package/project-transform/src/platform/host.ts +343 -0
- package/project-transform/src/platform/path.js +8 -0
- package/project-transform/src/platform/path.ts +20 -0
- package/project-transform/src/public_macro_api/macro_api.d.ts +1054 -0
- package/project-transform/src/public_macro_api/macro_semantic_types.d.ts +66 -0
- package/project-transform/src/public_macro_api/macro_types.d.ts +70 -0
- package/project-transform/src/run_program.js +14 -0
- package/project-transform/src/run_program.ts +33 -0
- package/project-transform/src/runtime/materialize.js +371 -0
- package/project-transform/src/runtime/materialize.ts +502 -0
- package/project-transform/src/runtime/on_demand.js +203 -0
- package/project-transform/src/runtime/on_demand.ts +305 -0
- package/project-transform/src/runtime/source_maps.js +205 -0
- package/project-transform/src/runtime/source_maps.ts +297 -0
- package/project-transform/src/runtime/transform.js +148 -0
- package/project-transform/src/runtime/transform.ts +295 -0
- package/project-transform/src/service/types.js +1 -0
- package/project-transform/src/service/types.ts +22 -0
- package/project-transform/src/soundscript_packages.js +477 -0
- package/project-transform/src/soundscript_packages.ts +754 -0
- package/project-transform/src/soundscript_runtime_specifiers.js +88 -0
- package/project-transform/src/soundscript_runtime_specifiers.ts +96 -0
- package/project-transform/src/stdlib/async.d.ts +81 -0
- package/project-transform/src/stdlib/async.js +213 -0
- package/project-transform/src/stdlib/async.ts +315 -0
- package/project-transform/src/stdlib/codec.d.ts +32 -0
- package/project-transform/src/stdlib/codec.js +30 -0
- package/project-transform/src/stdlib/codec.ts +76 -0
- package/project-transform/src/stdlib/compare.d.ts +28 -0
- package/project-transform/src/stdlib/compare.js +115 -0
- package/project-transform/src/stdlib/compare.ts +151 -0
- package/project-transform/src/stdlib/css.d.ts +16 -0
- package/project-transform/src/stdlib/css.js +9 -0
- package/project-transform/src/stdlib/css.ts +28 -0
- package/project-transform/src/stdlib/debug.d.ts +2 -0
- package/project-transform/src/stdlib/debug.js +9 -0
- package/project-transform/src/stdlib/debug.ts +10 -0
- package/project-transform/src/stdlib/decode.d.ts +86 -0
- package/project-transform/src/stdlib/decode.js +254 -0
- package/project-transform/src/stdlib/decode.ts +390 -0
- package/project-transform/src/stdlib/derive.d.ts +6 -0
- package/project-transform/src/stdlib/derive.js +7 -0
- package/project-transform/src/stdlib/derive.ts +7 -0
- package/project-transform/src/stdlib/encode.d.ts +100 -0
- package/project-transform/src/stdlib/encode.js +130 -0
- package/project-transform/src/stdlib/encode.ts +259 -0
- package/project-transform/src/stdlib/failures.d.ts +23 -0
- package/project-transform/src/stdlib/failures.js +41 -0
- package/project-transform/src/stdlib/failures.ts +64 -0
- package/project-transform/src/stdlib/fetch.d.ts +67 -0
- package/project-transform/src/stdlib/fetch.js +5 -0
- package/project-transform/src/stdlib/fetch.ts +11 -0
- package/project-transform/src/stdlib/graphql.d.ts +16 -0
- package/project-transform/src/stdlib/graphql.js +9 -0
- package/project-transform/src/stdlib/graphql.ts +28 -0
- package/project-transform/src/stdlib/hash.d.ts +34 -0
- package/project-transform/src/stdlib/hash.js +110 -0
- package/project-transform/src/stdlib/hash.ts +188 -0
- package/project-transform/src/stdlib/hkt.d.ts +40 -0
- package/project-transform/src/stdlib/hkt.js +3 -0
- package/project-transform/src/stdlib/hkt.ts +41 -0
- package/project-transform/src/stdlib/index.d.ts +9 -0
- package/project-transform/src/stdlib/index.js +15 -0
- package/project-transform/src/stdlib/index.ts +23 -0
- package/project-transform/src/stdlib/json.d.ts +125 -0
- package/project-transform/src/stdlib/json.js +764 -0
- package/project-transform/src/stdlib/json.ts +1034 -0
- package/project-transform/src/stdlib/match.d.ts +11 -0
- package/project-transform/src/stdlib/match.js +13 -0
- package/project-transform/src/stdlib/match.ts +26 -0
- package/project-transform/src/stdlib/numerics.d.ts +523 -0
- package/project-transform/src/stdlib/numerics.js +1356 -0
- package/project-transform/src/stdlib/numerics.ts +1937 -0
- package/project-transform/src/stdlib/random.d.ts +19 -0
- package/project-transform/src/stdlib/random.js +3 -0
- package/project-transform/src/stdlib/random.ts +5 -0
- package/project-transform/src/stdlib/result.d.ts +68 -0
- package/project-transform/src/stdlib/result.js +139 -0
- package/project-transform/src/stdlib/result.ts +248 -0
- package/project-transform/src/stdlib/sql.d.ts +22 -0
- package/project-transform/src/stdlib/sql.js +23 -0
- package/project-transform/src/stdlib/sql.ts +53 -0
- package/project-transform/src/stdlib/text.d.ts +24 -0
- package/project-transform/src/stdlib/text.js +3 -0
- package/project-transform/src/stdlib/text.ts +4 -0
- package/project-transform/src/stdlib/thunk.d.ts +2 -0
- package/project-transform/src/stdlib/thunk.js +9 -0
- package/project-transform/src/stdlib/thunk.ts +15 -0
- package/project-transform/src/stdlib/typeclasses.d.ts +57 -0
- package/project-transform/src/stdlib/typeclasses.js +78 -0
- package/project-transform/src/stdlib/typeclasses.ts +173 -0
- package/project-transform/src/stdlib/url.d.ts +37 -0
- package/project-transform/src/stdlib/url.js +3 -0
- package/project-transform/src/stdlib/url.ts +4 -0
- package/project-transform/src/stdlib/value.d.ts +9 -0
- package/project-transform/src/stdlib/value.js +104 -0
- package/project-transform/src/stdlib/value.ts +133 -0
- package/project-transform/src/test_installed_stdlib.js +147 -0
- package/project-transform/src/test_installed_stdlib.ts +245 -0
- package/project-transform/src/test_macro_package_fixture.js +50 -0
- package/project-transform/src/test_macro_package_fixture.ts +68 -0
- package/project-transform/src/value_deep_safe.js +191 -0
- package/project-transform/src/value_deep_safe.ts +273 -0
|
@@ -0,0 +1,1087 @@
|
|
|
1
|
+
import { assertEquals } from '@std/assert';
|
|
2
|
+
import { dirname, fromFileUrl, join } from './platform/path.ts';
|
|
3
|
+
import ts from 'typescript';
|
|
4
|
+
|
|
5
|
+
import { createSoundStdlibCompilerHost } from './bundled/sound_stdlib.ts';
|
|
6
|
+
import { compileProject } from './compiler/compile_project.ts';
|
|
7
|
+
import type { CompilerModuleIR } from './compiler/ir.ts';
|
|
8
|
+
import { lowerProgramToCompilerIR } from './compiler/lower.ts';
|
|
9
|
+
import type {
|
|
10
|
+
CompilerRuntimeAdaptObjectValueIR,
|
|
11
|
+
CompilerRuntimeAllocateFallbackObjectIR,
|
|
12
|
+
CompilerRuntimeAllocateSpecializedObjectIR,
|
|
13
|
+
CompilerRuntimeGetFallbackObjectPropertyIR,
|
|
14
|
+
CompilerRuntimeGetSpecializedObjectFieldIR,
|
|
15
|
+
CompilerRuntimeSetFallbackObjectPropertyIR,
|
|
16
|
+
CompilerRuntimeSpecializedObjectRepresentationIR,
|
|
17
|
+
} from './compiler/runtime_ir.ts';
|
|
18
|
+
import { loadConfig } from './config.ts';
|
|
19
|
+
import { instantiateSoundscriptWasmModule } from './compiler/wasm_js_host_runtime.ts';
|
|
20
|
+
|
|
21
|
+
export interface TempProjectFile {
|
|
22
|
+
path: string;
|
|
23
|
+
contents: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const REPO_ROOT = dirname(dirname(fromFileUrl(import.meta.url)));
|
|
27
|
+
const SOUNDSCRIPT_CLASS_TAG = '__soundscript_class_tag__';
|
|
28
|
+
const SOUNDSCRIPT_CLASS_CONSTRUCT = '__soundscript_class_construct';
|
|
29
|
+
const SOUNDSCRIPT_CLASS_BASE_CONSTRUCTOR = '__soundscript_class_base_constructor';
|
|
30
|
+
const SOUNDSCRIPT_CLOSURE_REF = Symbol('soundscript_closure_ref');
|
|
31
|
+
const SOUNDSCRIPT_SYNC_AWARE = Symbol('soundscript_sync_aware');
|
|
32
|
+
const SOUNDSCRIPT_ISOLATED_TESTS = 'SOUNDSCRIPT_ISOLATED_TESTS';
|
|
33
|
+
const SOUNDSCRIPT_ISOLATED_TEST_BATCH_SIZE = 'SOUNDSCRIPT_ISOLATED_TEST_BATCH_SIZE';
|
|
34
|
+
const DEFAULT_ISOLATED_TEST_BATCH_SIZE = 8;
|
|
35
|
+
|
|
36
|
+
let cachedCliTestFilterEnabled: boolean | undefined;
|
|
37
|
+
|
|
38
|
+
function getConfiguredIsolatedTestBatchSize(): number {
|
|
39
|
+
const rawValue = Deno.env.get(SOUNDSCRIPT_ISOLATED_TEST_BATCH_SIZE);
|
|
40
|
+
if (rawValue === undefined) {
|
|
41
|
+
return DEFAULT_ISOLATED_TEST_BATCH_SIZE;
|
|
42
|
+
}
|
|
43
|
+
const parsed = Number.parseInt(rawValue, 10);
|
|
44
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : DEFAULT_ISOLATED_TEST_BATCH_SIZE;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function getCliTestFilterEnabled(): boolean {
|
|
48
|
+
if (cachedCliTestFilterEnabled !== undefined) {
|
|
49
|
+
return cachedCliTestFilterEnabled;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const result = new Deno.Command('ps', {
|
|
53
|
+
args: ['-p', String(Deno.pid), '-o', 'command='],
|
|
54
|
+
stderr: 'piped',
|
|
55
|
+
stdout: 'piped',
|
|
56
|
+
}).outputSync();
|
|
57
|
+
|
|
58
|
+
if (!result.success) {
|
|
59
|
+
cachedCliTestFilterEnabled = true;
|
|
60
|
+
return cachedCliTestFilterEnabled;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const commandLine = new TextDecoder().decode(result.stdout);
|
|
64
|
+
cachedCliTestFilterEnabled = /(?:^|\s)(?:--filter|-f)(?:=|\s|$)/.test(commandLine);
|
|
65
|
+
return cachedCliTestFilterEnabled;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function createIsolatedTestRegistrar(fileUrl: string) {
|
|
69
|
+
const isolatedTestNamesValue = Deno.env.get(SOUNDSCRIPT_ISOLATED_TESTS);
|
|
70
|
+
const isolatedTestNames = isolatedTestNamesValue === undefined
|
|
71
|
+
? undefined
|
|
72
|
+
: JSON.parse(isolatedTestNamesValue) as string[];
|
|
73
|
+
const isolatedTestNameSet = isolatedTestNames === undefined
|
|
74
|
+
? undefined
|
|
75
|
+
: new Set(isolatedTestNames);
|
|
76
|
+
const filePath = fromFileUrl(fileUrl);
|
|
77
|
+
const registeredTestNames: string[] = [];
|
|
78
|
+
const batchRuns = new Map<number, { ownerName: string; promise: Promise<void> }>();
|
|
79
|
+
const batchSize = isolatedTestNameSet === undefined && !getCliTestFilterEnabled()
|
|
80
|
+
? getConfiguredIsolatedTestBatchSize()
|
|
81
|
+
: 1;
|
|
82
|
+
|
|
83
|
+
const runIsolatedTests = async (testNames: string[]) => {
|
|
84
|
+
const command = new Deno.Command(Deno.execPath(), {
|
|
85
|
+
args: [
|
|
86
|
+
'test',
|
|
87
|
+
'--no-check',
|
|
88
|
+
'--allow-env',
|
|
89
|
+
'--allow-read',
|
|
90
|
+
'--allow-write',
|
|
91
|
+
'--allow-run',
|
|
92
|
+
filePath,
|
|
93
|
+
],
|
|
94
|
+
cwd: REPO_ROOT,
|
|
95
|
+
env: {
|
|
96
|
+
...Deno.env.toObject(),
|
|
97
|
+
[SOUNDSCRIPT_ISOLATED_TESTS]: JSON.stringify(testNames),
|
|
98
|
+
},
|
|
99
|
+
stderr: 'piped',
|
|
100
|
+
stdout: 'piped',
|
|
101
|
+
});
|
|
102
|
+
const result = await command.output();
|
|
103
|
+
const stdout = new TextDecoder().decode(result.stdout);
|
|
104
|
+
const stderr = new TextDecoder().decode(result.stderr);
|
|
105
|
+
assertEquals(
|
|
106
|
+
result.success,
|
|
107
|
+
true,
|
|
108
|
+
[
|
|
109
|
+
`isolated compiler test batch failed: ${testNames.join(', ')}`,
|
|
110
|
+
`stdout:\n${stdout}`,
|
|
111
|
+
`stderr:\n${stderr}`,
|
|
112
|
+
].join('\n\n'),
|
|
113
|
+
);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
return (name: string, fn: () => Promise<void> | void): void => {
|
|
117
|
+
const testIndex = registeredTestNames.length;
|
|
118
|
+
registeredTestNames.push(name);
|
|
119
|
+
|
|
120
|
+
if (isolatedTestNameSet !== undefined && !isolatedTestNameSet.has(name)) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
Deno.test({
|
|
125
|
+
name,
|
|
126
|
+
sanitizeOps: false,
|
|
127
|
+
sanitizeResources: false,
|
|
128
|
+
async fn() {
|
|
129
|
+
if (isolatedTestNameSet !== undefined) {
|
|
130
|
+
await fn();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const batchId = Math.floor(testIndex / batchSize);
|
|
135
|
+
const existingBatchRun = batchRuns.get(batchId);
|
|
136
|
+
if (existingBatchRun !== undefined) {
|
|
137
|
+
if (existingBatchRun.ownerName !== name) {
|
|
138
|
+
try {
|
|
139
|
+
await existingBatchRun.promise;
|
|
140
|
+
} catch {
|
|
141
|
+
// Let the owner test report the batch failure once.
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
await existingBatchRun.promise;
|
|
145
|
+
}
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const batchStart = batchId * batchSize;
|
|
150
|
+
const batchEnd = batchStart + batchSize;
|
|
151
|
+
const batchTestNames = registeredTestNames.slice(batchStart, batchEnd);
|
|
152
|
+
const batchPromise = runIsolatedTests(batchTestNames);
|
|
153
|
+
batchRuns.set(batchId, { ownerName: name, promise: batchPromise });
|
|
154
|
+
await batchPromise;
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export async function createTempProject(files: TempProjectFile[]): Promise<string> {
|
|
161
|
+
const tempDirectory = await Deno.makeTempDir({ prefix: 'sound-tsc-compiler-' });
|
|
162
|
+
|
|
163
|
+
for (const file of files) {
|
|
164
|
+
const absolutePath = join(tempDirectory, file.path);
|
|
165
|
+
await Deno.mkdir(dirname(absolutePath), { recursive: true });
|
|
166
|
+
await Deno.writeTextFile(absolutePath, file.contents);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return tempDirectory;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function getOutputDirectory(tempDirectory: string): string {
|
|
173
|
+
return join(tempDirectory, 'soundscript-out');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export function getWatPath(tempDirectory: string): string {
|
|
177
|
+
return join(getOutputDirectory(tempDirectory), 'module.wat');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export async function readWatArtifact(tempDirectory: string): Promise<string> {
|
|
181
|
+
return await Deno.readTextFile(getWatPath(tempDirectory));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export async function readCompiledWasmBytes(tempDirectory: string): Promise<Uint8Array> {
|
|
185
|
+
const watPath = getWatPath(tempDirectory);
|
|
186
|
+
const wasmPath = join(getOutputDirectory(tempDirectory), 'module.test.wasm');
|
|
187
|
+
const command = new Deno.Command('wasm-tools', {
|
|
188
|
+
args: ['parse', watPath, '-o', wasmPath],
|
|
189
|
+
stderr: 'piped',
|
|
190
|
+
stdout: 'piped',
|
|
191
|
+
});
|
|
192
|
+
const result = await command.output();
|
|
193
|
+
if (!result.success) {
|
|
194
|
+
throw new Error(new TextDecoder().decode(result.stderr).trim());
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return await Deno.readFile(wasmPath);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function createJsHostImports(
|
|
201
|
+
instanceCell: { instance: WebAssembly.Instance | null },
|
|
202
|
+
): WebAssembly.Imports {
|
|
203
|
+
const heapIdentityCache = new WeakMap<object, unknown>();
|
|
204
|
+
const hostParamIdentityCache = new WeakMap<object, Map<string, unknown>>();
|
|
205
|
+
const hostPromiseToInternalCache = new WeakMap<object, object>();
|
|
206
|
+
const internalPromiseToHostCache = new WeakMap<object, Promise<unknown>>();
|
|
207
|
+
const classConstructorWrappers = new Map<number, Function>();
|
|
208
|
+
const getClassMethodSyncExportName = (tag: number, propertyName: string): string =>
|
|
209
|
+
`__soundscript_sync_class_method_${tag}__${
|
|
210
|
+
[...new TextEncoder().encode(propertyName)]
|
|
211
|
+
.map((byte) => byte.toString(16).padStart(2, '0'))
|
|
212
|
+
.join('')
|
|
213
|
+
}`;
|
|
214
|
+
const getClassMethodSyncFromHostExportName = (tag: number, propertyName: string): string =>
|
|
215
|
+
`__soundscript_sync_from_class_method_${tag}__${
|
|
216
|
+
[...new TextEncoder().encode(propertyName)]
|
|
217
|
+
.map((byte) => byte.toString(16).padStart(2, '0'))
|
|
218
|
+
.join('')
|
|
219
|
+
}`;
|
|
220
|
+
const getClassStaticMethodSyncExportName = (tag: number, propertyName: string): string =>
|
|
221
|
+
`__soundscript_sync_class_static_method_${tag}__${
|
|
222
|
+
[...new TextEncoder().encode(propertyName)]
|
|
223
|
+
.map((byte) => byte.toString(16).padStart(2, '0'))
|
|
224
|
+
.join('')
|
|
225
|
+
}`;
|
|
226
|
+
const getClassStaticMethodSyncFromHostExportName = (tag: number, propertyName: string): string =>
|
|
227
|
+
`__soundscript_sync_from_class_static_method_${tag}__${
|
|
228
|
+
[...new TextEncoder().encode(propertyName)]
|
|
229
|
+
.map((byte) => byte.toString(16).padStart(2, '0'))
|
|
230
|
+
.join('')
|
|
231
|
+
}`;
|
|
232
|
+
|
|
233
|
+
const expectHeapIdentityKey = (value: unknown): object => {
|
|
234
|
+
if (
|
|
235
|
+
(typeof value !== 'object' && typeof value !== 'function') ||
|
|
236
|
+
value === null
|
|
237
|
+
) {
|
|
238
|
+
throw new TypeError('Expected wasm heap reference for host identity cache.');
|
|
239
|
+
}
|
|
240
|
+
return value;
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
const getOrCreateHostClassConstructor = (tag: number): Function => {
|
|
244
|
+
const existing = classConstructorWrappers.get(tag);
|
|
245
|
+
if (existing) {
|
|
246
|
+
return existing;
|
|
247
|
+
}
|
|
248
|
+
const wrapper = function SoundscriptClassWrapper(this: unknown, ...args: unknown[]): unknown {
|
|
249
|
+
if (new.target === undefined) {
|
|
250
|
+
throw new TypeError('Class constructors must be invoked with new.');
|
|
251
|
+
}
|
|
252
|
+
const construct =
|
|
253
|
+
(wrapper as unknown as Record<string, unknown>)[SOUNDSCRIPT_CLASS_CONSTRUCT];
|
|
254
|
+
if (typeof construct !== 'function') {
|
|
255
|
+
throw new TypeError('Compiled class constructor wrapper is missing construct hook.');
|
|
256
|
+
}
|
|
257
|
+
return construct(...args);
|
|
258
|
+
};
|
|
259
|
+
Object.defineProperty(wrapper, 'name', {
|
|
260
|
+
configurable: true,
|
|
261
|
+
value: `SoundscriptClass${tag}`,
|
|
262
|
+
});
|
|
263
|
+
Object.defineProperty(wrapper, Symbol.hasInstance, {
|
|
264
|
+
configurable: true,
|
|
265
|
+
value(instance: unknown) {
|
|
266
|
+
if (typeof instance !== 'object' || instance === null) {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
return wrapper.prototype.isPrototypeOf(instance);
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
Object.defineProperty(wrapper.prototype, 'constructor', {
|
|
273
|
+
configurable: true,
|
|
274
|
+
enumerable: false,
|
|
275
|
+
value: wrapper,
|
|
276
|
+
writable: true,
|
|
277
|
+
});
|
|
278
|
+
Object.defineProperty(wrapper, SOUNDSCRIPT_CLASS_TAG, {
|
|
279
|
+
configurable: true,
|
|
280
|
+
enumerable: false,
|
|
281
|
+
value: Number(tag),
|
|
282
|
+
writable: true,
|
|
283
|
+
});
|
|
284
|
+
classConstructorWrappers.set(tag, wrapper);
|
|
285
|
+
return wrapper;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
const syncClassPrototype = (value: unknown) => {
|
|
289
|
+
if (typeof value !== 'object' || value === null) {
|
|
290
|
+
throw new TypeError('Expected JS object for soundscript_object.sync_class_prototype.');
|
|
291
|
+
}
|
|
292
|
+
const objectRecord = value as Record<string, unknown>;
|
|
293
|
+
const tag = objectRecord[SOUNDSCRIPT_CLASS_TAG];
|
|
294
|
+
if (typeof tag !== 'number') {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
Object.setPrototypeOf(value, getOrCreateHostClassConstructor(Number(tag)).prototype);
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const syncHostBoundaryValue = (value: unknown): unknown => {
|
|
301
|
+
if (Array.isArray(value)) {
|
|
302
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
303
|
+
value[index] = syncHostBoundaryValue(value[index]);
|
|
304
|
+
}
|
|
305
|
+
return value;
|
|
306
|
+
}
|
|
307
|
+
if (typeof value === 'object' && value !== null) {
|
|
308
|
+
syncClassPrototype(value);
|
|
309
|
+
}
|
|
310
|
+
return value;
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
const wrapHostMethodIfNeeded = (
|
|
314
|
+
target: Record<string, unknown>,
|
|
315
|
+
propertyName: string,
|
|
316
|
+
value: unknown,
|
|
317
|
+
): unknown => {
|
|
318
|
+
if (typeof value !== 'function') {
|
|
319
|
+
return value;
|
|
320
|
+
}
|
|
321
|
+
if ((value as unknown as Record<PropertyKey, unknown>)[SOUNDSCRIPT_SYNC_AWARE] === true) {
|
|
322
|
+
return value;
|
|
323
|
+
}
|
|
324
|
+
const tag = target[SOUNDSCRIPT_CLASS_TAG];
|
|
325
|
+
const closureRef = (value as unknown as Record<PropertyKey, unknown>)[SOUNDSCRIPT_CLOSURE_REF];
|
|
326
|
+
if (typeof tag !== 'number' || closureRef === undefined) {
|
|
327
|
+
return value;
|
|
328
|
+
}
|
|
329
|
+
const instance = instanceCell.instance;
|
|
330
|
+
if (!instance) {
|
|
331
|
+
return value;
|
|
332
|
+
}
|
|
333
|
+
const syncExportName = typeof target === 'function'
|
|
334
|
+
? getClassStaticMethodSyncExportName(Number(tag), propertyName)
|
|
335
|
+
: getClassMethodSyncExportName(Number(tag), propertyName);
|
|
336
|
+
const syncFromHostExportName = typeof target === 'function'
|
|
337
|
+
? getClassStaticMethodSyncFromHostExportName(Number(tag), propertyName)
|
|
338
|
+
: getClassMethodSyncFromHostExportName(Number(tag), propertyName);
|
|
339
|
+
const sync = instance.exports[syncExportName];
|
|
340
|
+
const syncFromHost = instance.exports[syncFromHostExportName];
|
|
341
|
+
if (typeof sync !== 'function' && typeof syncFromHost !== 'function') {
|
|
342
|
+
return value;
|
|
343
|
+
}
|
|
344
|
+
const callable = value as (...args: unknown[]) => unknown;
|
|
345
|
+
const wrapped = function (this: unknown, ...args: unknown[]): unknown {
|
|
346
|
+
if (typeof syncFromHost === 'function') {
|
|
347
|
+
syncFromHost(closureRef, target);
|
|
348
|
+
}
|
|
349
|
+
const result = callable.apply(this, args);
|
|
350
|
+
if (typeof sync === 'function') {
|
|
351
|
+
sync(closureRef, target);
|
|
352
|
+
}
|
|
353
|
+
return result;
|
|
354
|
+
};
|
|
355
|
+
Object.defineProperty(wrapped, SOUNDSCRIPT_CLOSURE_REF, {
|
|
356
|
+
configurable: true,
|
|
357
|
+
enumerable: false,
|
|
358
|
+
value: closureRef,
|
|
359
|
+
writable: false,
|
|
360
|
+
});
|
|
361
|
+
return wrapped;
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
return {
|
|
365
|
+
soundscript_array: {
|
|
366
|
+
empty: () => [],
|
|
367
|
+
empty_number: () => [],
|
|
368
|
+
empty_boolean: () => [],
|
|
369
|
+
clear: (value: unknown) => {
|
|
370
|
+
if (!Array.isArray(value)) {
|
|
371
|
+
throw new TypeError('Expected JS array for soundscript_array.clear.');
|
|
372
|
+
}
|
|
373
|
+
value.length = 0;
|
|
374
|
+
},
|
|
375
|
+
length: (value: unknown) => {
|
|
376
|
+
if (!Array.isArray(value)) {
|
|
377
|
+
throw new TypeError('Expected JS array for soundscript_array.length.');
|
|
378
|
+
}
|
|
379
|
+
return value.length;
|
|
380
|
+
},
|
|
381
|
+
same: (left: unknown, right: unknown) => Number(Object.is(left, right)),
|
|
382
|
+
get: (value: unknown, index: number) => {
|
|
383
|
+
if (!Array.isArray(value)) {
|
|
384
|
+
throw new TypeError('Expected JS array for soundscript_array.get.');
|
|
385
|
+
}
|
|
386
|
+
return value[Number(index)];
|
|
387
|
+
},
|
|
388
|
+
get_number: (value: unknown, index: number) => {
|
|
389
|
+
if (!Array.isArray(value)) {
|
|
390
|
+
throw new TypeError('Expected JS array for soundscript_array.get_number.');
|
|
391
|
+
}
|
|
392
|
+
return Number(value[Number(index)]);
|
|
393
|
+
},
|
|
394
|
+
get_boolean: (value: unknown, index: number) => {
|
|
395
|
+
if (!Array.isArray(value)) {
|
|
396
|
+
throw new TypeError('Expected JS array for soundscript_array.get_boolean.');
|
|
397
|
+
}
|
|
398
|
+
return Boolean(value[Number(index)]) ? 1 : 0;
|
|
399
|
+
},
|
|
400
|
+
push: (target: unknown, value: unknown) => {
|
|
401
|
+
if (!Array.isArray(target)) {
|
|
402
|
+
throw new TypeError('Expected JS array for soundscript_array.push.');
|
|
403
|
+
}
|
|
404
|
+
target.push(syncHostBoundaryValue(value));
|
|
405
|
+
},
|
|
406
|
+
push_number: (target: unknown, value: unknown) => {
|
|
407
|
+
if (!Array.isArray(target)) {
|
|
408
|
+
throw new TypeError('Expected JS array for soundscript_array.push_number.');
|
|
409
|
+
}
|
|
410
|
+
target.push(Number(value));
|
|
411
|
+
},
|
|
412
|
+
push_boolean: (target: unknown, value: unknown) => {
|
|
413
|
+
if (!Array.isArray(target)) {
|
|
414
|
+
throw new TypeError('Expected JS array for soundscript_array.push_boolean.');
|
|
415
|
+
}
|
|
416
|
+
target.push(Boolean(value));
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
soundscript_length_view: {
|
|
420
|
+
length: (value: unknown) => {
|
|
421
|
+
if (
|
|
422
|
+
value === null ||
|
|
423
|
+
value === undefined ||
|
|
424
|
+
(!Array.isArray(value) && typeof value !== 'string' &&
|
|
425
|
+
(typeof value !== 'object' || value === null || !('length' in value)))
|
|
426
|
+
) {
|
|
427
|
+
throw new TypeError('Expected string, array, or length-bearing object.');
|
|
428
|
+
}
|
|
429
|
+
return Number((value as { length: unknown }).length);
|
|
430
|
+
},
|
|
431
|
+
from_length: (value: number) => ({ length: Number(value) }),
|
|
432
|
+
},
|
|
433
|
+
soundscript_object: new Proxy({}, {
|
|
434
|
+
get(_target, property) {
|
|
435
|
+
if (property === 'same') {
|
|
436
|
+
return (left: unknown, right: unknown) => Number(left === right);
|
|
437
|
+
}
|
|
438
|
+
if (property === 'empty') {
|
|
439
|
+
return () => ({});
|
|
440
|
+
}
|
|
441
|
+
if (property === 'lookup_cached') {
|
|
442
|
+
return (value: unknown) => heapIdentityCache.get(expectHeapIdentityKey(value)) ?? null;
|
|
443
|
+
}
|
|
444
|
+
if (property === 'remember_cached') {
|
|
445
|
+
return (value: unknown, hostValue: unknown) => {
|
|
446
|
+
heapIdentityCache.set(expectHeapIdentityKey(value), hostValue);
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
if (property === 'get_class_tag') {
|
|
450
|
+
return (value: unknown) => {
|
|
451
|
+
if ((typeof value !== 'object' && typeof value !== 'function') || value === null) {
|
|
452
|
+
throw new TypeError(
|
|
453
|
+
'Expected JS object or function for soundscript_object.get_class_tag.',
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
const objectRecord = value as Record<string, unknown>;
|
|
457
|
+
return typeof objectRecord[SOUNDSCRIPT_CLASS_TAG] === 'number'
|
|
458
|
+
? Number(objectRecord[SOUNDSCRIPT_CLASS_TAG])
|
|
459
|
+
: -1;
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
if (property === 'set_class_tag') {
|
|
463
|
+
return (value: unknown, next: number) => {
|
|
464
|
+
if ((typeof value !== 'object' && typeof value !== 'function') || value === null) {
|
|
465
|
+
throw new TypeError(
|
|
466
|
+
'Expected JS object or function for soundscript_object.set_class_tag.',
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
Object.defineProperty(value, SOUNDSCRIPT_CLASS_TAG, {
|
|
470
|
+
configurable: true,
|
|
471
|
+
enumerable: false,
|
|
472
|
+
value: Number(next),
|
|
473
|
+
writable: true,
|
|
474
|
+
});
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
if (property === 'class_constructor_from_tag') {
|
|
478
|
+
return (tag: number) => getOrCreateHostClassConstructor(Number(tag));
|
|
479
|
+
}
|
|
480
|
+
if (property === 'sync_class_prototype') {
|
|
481
|
+
return syncClassPrototype;
|
|
482
|
+
}
|
|
483
|
+
if (typeof property !== 'string') {
|
|
484
|
+
return undefined;
|
|
485
|
+
}
|
|
486
|
+
const expectMapValue = (value: unknown): Map<unknown, unknown> => {
|
|
487
|
+
if (!(value instanceof Map)) {
|
|
488
|
+
throw new TypeError('Expected JS Map for soundscript_object collection host boundary.');
|
|
489
|
+
}
|
|
490
|
+
return value;
|
|
491
|
+
};
|
|
492
|
+
const expectSetValue = (value: unknown): Set<unknown> => {
|
|
493
|
+
if (!(value instanceof Set)) {
|
|
494
|
+
throw new TypeError('Expected JS Set for soundscript_object collection host boundary.');
|
|
495
|
+
}
|
|
496
|
+
return value;
|
|
497
|
+
};
|
|
498
|
+
if (property === 'map_keys') {
|
|
499
|
+
return (value: unknown) =>
|
|
500
|
+
Array.from(expectMapValue(value).keys(), (entry) => String(entry));
|
|
501
|
+
}
|
|
502
|
+
if (property === 'map_values_number') {
|
|
503
|
+
return (value: unknown) =>
|
|
504
|
+
Array.from(expectMapValue(value).values(), (entry) => Number(entry));
|
|
505
|
+
}
|
|
506
|
+
if (property === 'map_values_boolean') {
|
|
507
|
+
return (value: unknown) =>
|
|
508
|
+
Array.from(expectMapValue(value).values(), (entry) => Boolean(entry));
|
|
509
|
+
}
|
|
510
|
+
if (property === 'map_values_string') {
|
|
511
|
+
return (value: unknown) =>
|
|
512
|
+
Array.from(expectMapValue(value).values(), (entry) => String(entry));
|
|
513
|
+
}
|
|
514
|
+
if (property === 'set_values_number') {
|
|
515
|
+
return (value: unknown) =>
|
|
516
|
+
Array.from(expectSetValue(value).values(), (entry) => Number(entry));
|
|
517
|
+
}
|
|
518
|
+
if (property === 'set_values_boolean') {
|
|
519
|
+
return (value: unknown) =>
|
|
520
|
+
Array.from(expectSetValue(value).values(), (entry) => Boolean(entry));
|
|
521
|
+
}
|
|
522
|
+
if (property === 'set_values_string') {
|
|
523
|
+
return (value: unknown) =>
|
|
524
|
+
Array.from(expectSetValue(value).values(), (entry) => String(entry));
|
|
525
|
+
}
|
|
526
|
+
if (property === 'set_values_key') {
|
|
527
|
+
return () => '__set_values';
|
|
528
|
+
}
|
|
529
|
+
const match =
|
|
530
|
+
/^(get_number|get_boolean|get_closure|set_number|set_boolean|set_closure|has|get_tagged|set_tagged):(.*)$/
|
|
531
|
+
.exec(property);
|
|
532
|
+
const paramCacheMatch = /^(lookup_param_cached|remember_param_cached):(.*)$/.exec(property);
|
|
533
|
+
if (paramCacheMatch) {
|
|
534
|
+
const kind = paramCacheMatch[1];
|
|
535
|
+
const cacheKey = decodeURIComponent(paramCacheMatch[2]!);
|
|
536
|
+
const expectHostIdentityKey = (value: unknown): object => {
|
|
537
|
+
if ((typeof value !== 'object' && typeof value !== 'function') || value === null) {
|
|
538
|
+
throw new TypeError(
|
|
539
|
+
'Expected JS object for soundscript_object param identity cache.',
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
return value;
|
|
543
|
+
};
|
|
544
|
+
if (kind === 'lookup_param_cached') {
|
|
545
|
+
return (value: unknown) =>
|
|
546
|
+
hostParamIdentityCache.get(expectHostIdentityKey(value))?.get(cacheKey) ?? null;
|
|
547
|
+
}
|
|
548
|
+
return (value: unknown, heapValue: unknown) => {
|
|
549
|
+
const hostKey = expectHostIdentityKey(value);
|
|
550
|
+
const existing = hostParamIdentityCache.get(hostKey);
|
|
551
|
+
if (existing) {
|
|
552
|
+
existing.set(cacheKey, heapValue);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
const created = new Map<string, unknown>();
|
|
556
|
+
created.set(cacheKey, heapValue);
|
|
557
|
+
hostParamIdentityCache.set(hostKey, created);
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
if (!match) {
|
|
561
|
+
return undefined;
|
|
562
|
+
}
|
|
563
|
+
const kind = match[1];
|
|
564
|
+
const propertyName = decodeURIComponent(match[2]);
|
|
565
|
+
const expectObjectRecord = (value: unknown): Record<string, unknown> => {
|
|
566
|
+
if ((typeof value !== 'object' && typeof value !== 'function') || value === null) {
|
|
567
|
+
throw new TypeError(
|
|
568
|
+
'Expected JS object or function for soundscript_object host boundary.',
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
return value as Record<string, unknown>;
|
|
572
|
+
};
|
|
573
|
+
switch (kind) {
|
|
574
|
+
case 'has':
|
|
575
|
+
return (value: unknown) =>
|
|
576
|
+
Number(Object.prototype.hasOwnProperty.call(expectObjectRecord(value), propertyName));
|
|
577
|
+
case 'get_number':
|
|
578
|
+
return (value: unknown) => Number(expectObjectRecord(value)[propertyName]);
|
|
579
|
+
case 'get_boolean':
|
|
580
|
+
return (value: unknown) => Number(Boolean(expectObjectRecord(value)[propertyName]));
|
|
581
|
+
case 'get_closure':
|
|
582
|
+
return (value: unknown) => {
|
|
583
|
+
const objectRecord = expectObjectRecord(value);
|
|
584
|
+
const propertyValue = objectRecord[propertyName];
|
|
585
|
+
return typeof propertyValue === 'function'
|
|
586
|
+
? propertyValue.bind(value)
|
|
587
|
+
: propertyValue;
|
|
588
|
+
};
|
|
589
|
+
case 'get_tagged':
|
|
590
|
+
return (value: unknown) => expectObjectRecord(value)[propertyName];
|
|
591
|
+
case 'set_number':
|
|
592
|
+
return (value: unknown, next: number) => {
|
|
593
|
+
expectObjectRecord(value)[propertyName] = Number(next);
|
|
594
|
+
};
|
|
595
|
+
case 'set_boolean':
|
|
596
|
+
return (value: unknown, next: number) => {
|
|
597
|
+
expectObjectRecord(value)[propertyName] = next !== 0;
|
|
598
|
+
};
|
|
599
|
+
case 'set_closure':
|
|
600
|
+
return (value: unknown, next: unknown) => {
|
|
601
|
+
const objectRecord = expectObjectRecord(value);
|
|
602
|
+
objectRecord[propertyName] = wrapHostMethodIfNeeded(objectRecord, propertyName, next);
|
|
603
|
+
};
|
|
604
|
+
case 'set_tagged':
|
|
605
|
+
return (value: unknown, next: unknown) => {
|
|
606
|
+
const objectRecord = expectObjectRecord(value);
|
|
607
|
+
objectRecord[propertyName] = syncHostBoundaryValue(next);
|
|
608
|
+
if (
|
|
609
|
+
propertyName === SOUNDSCRIPT_CLASS_BASE_CONSTRUCTOR &&
|
|
610
|
+
typeof value === 'function' &&
|
|
611
|
+
typeof next === 'function'
|
|
612
|
+
) {
|
|
613
|
+
Object.setPrototypeOf(value, next);
|
|
614
|
+
if (
|
|
615
|
+
typeof (value as { prototype?: unknown }).prototype === 'object' &&
|
|
616
|
+
(value as { prototype?: unknown }).prototype !== null &&
|
|
617
|
+
typeof (next as { prototype?: unknown }).prototype === 'object' &&
|
|
618
|
+
(next as { prototype?: unknown }).prototype !== null
|
|
619
|
+
) {
|
|
620
|
+
Object.setPrototypeOf(
|
|
621
|
+
(value as { prototype: object }).prototype,
|
|
622
|
+
(next as { prototype: object }).prototype,
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
default:
|
|
628
|
+
return undefined;
|
|
629
|
+
}
|
|
630
|
+
},
|
|
631
|
+
}),
|
|
632
|
+
soundscript_string: {
|
|
633
|
+
empty: () => '',
|
|
634
|
+
from_char_code: (value: number) => String.fromCharCode(Number(value)),
|
|
635
|
+
length: (value: unknown) => String(value).length,
|
|
636
|
+
char_at: (value: unknown, index: number) => String(value).charAt(Number(index)),
|
|
637
|
+
char_code_at: (value: unknown, index: number) => String(value).charCodeAt(Number(index)),
|
|
638
|
+
to_upper_case: (value: unknown) => String(value).toUpperCase(),
|
|
639
|
+
to_lower_case: (value: unknown) => String(value).toLowerCase(),
|
|
640
|
+
trim: (value: unknown) => String(value).trim(),
|
|
641
|
+
trim_start: (value: unknown) => String(value).trimStart(),
|
|
642
|
+
trim_end: (value: unknown) => String(value).trimEnd(),
|
|
643
|
+
starts_with: (value: unknown, search: unknown) =>
|
|
644
|
+
Number(String(value).startsWith(String(search))),
|
|
645
|
+
ends_with: (value: unknown, search: unknown) =>
|
|
646
|
+
Number(String(value).endsWith(String(search))),
|
|
647
|
+
includes: (value: unknown, search: unknown) => Number(String(value).includes(String(search))),
|
|
648
|
+
index_of: (value: unknown, search: unknown) => String(value).indexOf(String(search)),
|
|
649
|
+
last_index_of: (value: unknown, search: unknown) => String(value).lastIndexOf(String(search)),
|
|
650
|
+
slice: (value: unknown, start: number, end: number, hasEnd: number) =>
|
|
651
|
+
hasEnd
|
|
652
|
+
? String(value).slice(Number(start), Number(end))
|
|
653
|
+
: String(value).slice(Number(start)),
|
|
654
|
+
substring: (value: unknown, start: number, end: number, hasEnd: number) =>
|
|
655
|
+
hasEnd
|
|
656
|
+
? String(value).substring(Number(start), Number(end))
|
|
657
|
+
: String(value).substring(Number(start)),
|
|
658
|
+
concat: (left: unknown, right: unknown) => String(left) + String(right),
|
|
659
|
+
equals: (left: unknown, right: unknown) => Number(String(left) === String(right)),
|
|
660
|
+
},
|
|
661
|
+
soundscript_tagged: {
|
|
662
|
+
undefined_value: () => undefined,
|
|
663
|
+
type_tag: (value: unknown) => {
|
|
664
|
+
if (value === undefined) {
|
|
665
|
+
return 0;
|
|
666
|
+
}
|
|
667
|
+
if (typeof value === 'boolean') {
|
|
668
|
+
return 1;
|
|
669
|
+
}
|
|
670
|
+
if (typeof value === 'number') {
|
|
671
|
+
return 2;
|
|
672
|
+
}
|
|
673
|
+
if (typeof value === 'string') {
|
|
674
|
+
return 3;
|
|
675
|
+
}
|
|
676
|
+
if (typeof value === 'object' || typeof value === 'function') {
|
|
677
|
+
if (value === null) {
|
|
678
|
+
return 6;
|
|
679
|
+
}
|
|
680
|
+
return 4;
|
|
681
|
+
}
|
|
682
|
+
if (value === null) {
|
|
683
|
+
return 6;
|
|
684
|
+
}
|
|
685
|
+
throw new Error(`Unsupported tagged host value: ${String(value)}`);
|
|
686
|
+
},
|
|
687
|
+
number_value: (value: unknown) => Number(value),
|
|
688
|
+
boolean_value: (value: unknown) => Number(Boolean(value)),
|
|
689
|
+
from_number: (value: number) => Number(value),
|
|
690
|
+
from_boolean: (value: number) => value !== 0,
|
|
691
|
+
},
|
|
692
|
+
soundscript_closure: new Proxy({}, {
|
|
693
|
+
get(_target, property) {
|
|
694
|
+
if (typeof property !== 'string') {
|
|
695
|
+
return undefined;
|
|
696
|
+
}
|
|
697
|
+
const callMatch = /^call_(\d+)$/.exec(property);
|
|
698
|
+
if (callMatch) {
|
|
699
|
+
return (callback: unknown, ...args: unknown[]) => {
|
|
700
|
+
if (typeof callback !== 'function') {
|
|
701
|
+
throw new TypeError('Expected JS function for soundscript_closure.call.');
|
|
702
|
+
}
|
|
703
|
+
return callback(...args);
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
const toHostSyncMatch = /^to_host_sync_(\d+):(.*)$/.exec(property);
|
|
707
|
+
if (toHostSyncMatch) {
|
|
708
|
+
const signatureId = Number(toHostSyncMatch[1]);
|
|
709
|
+
const syncExportName = decodeURIComponent(toHostSyncMatch[2] ?? '');
|
|
710
|
+
return (target: unknown, closure: unknown) => {
|
|
711
|
+
const wrapped = (...args: unknown[]) => {
|
|
712
|
+
const instance = instanceCell.instance;
|
|
713
|
+
if (!instance) {
|
|
714
|
+
throw new Error('Closure export wrapper invoked before instantiation completed.');
|
|
715
|
+
}
|
|
716
|
+
const invoke = instance.exports[`__soundscript_closure_invoke_${signatureId}`];
|
|
717
|
+
if (typeof invoke !== 'function') {
|
|
718
|
+
throw new Error(`Missing exported closure invoker for signature ${signatureId}.`);
|
|
719
|
+
}
|
|
720
|
+
const sync = instance.exports[syncExportName];
|
|
721
|
+
if (typeof sync !== 'function') {
|
|
722
|
+
throw new Error(`Missing exported closure sync helper ${syncExportName}.`);
|
|
723
|
+
}
|
|
724
|
+
const syncFromHostExportName =
|
|
725
|
+
syncExportName.startsWith('__soundscript_sync_class_method_')
|
|
726
|
+
? syncExportName.replace(
|
|
727
|
+
'__soundscript_sync_class_method_',
|
|
728
|
+
'__soundscript_sync_from_class_method_',
|
|
729
|
+
)
|
|
730
|
+
: syncExportName.startsWith('__soundscript_sync_class_static_method_')
|
|
731
|
+
? syncExportName.replace(
|
|
732
|
+
'__soundscript_sync_class_static_method_',
|
|
733
|
+
'__soundscript_sync_from_class_static_method_',
|
|
734
|
+
)
|
|
735
|
+
: null;
|
|
736
|
+
const syncFromHost = syncFromHostExportName
|
|
737
|
+
? instance.exports[syncFromHostExportName]
|
|
738
|
+
: undefined;
|
|
739
|
+
if (typeof syncFromHost === 'function') {
|
|
740
|
+
syncFromHost(closure, target);
|
|
741
|
+
}
|
|
742
|
+
const result = invoke(closure, ...args);
|
|
743
|
+
sync(closure, target);
|
|
744
|
+
return result;
|
|
745
|
+
};
|
|
746
|
+
Object.defineProperty(wrapped, SOUNDSCRIPT_CLOSURE_REF, {
|
|
747
|
+
configurable: true,
|
|
748
|
+
enumerable: false,
|
|
749
|
+
value: closure,
|
|
750
|
+
writable: false,
|
|
751
|
+
});
|
|
752
|
+
Object.defineProperty(wrapped, SOUNDSCRIPT_SYNC_AWARE, {
|
|
753
|
+
configurable: true,
|
|
754
|
+
enumerable: false,
|
|
755
|
+
value: true,
|
|
756
|
+
writable: false,
|
|
757
|
+
});
|
|
758
|
+
return wrapped;
|
|
759
|
+
};
|
|
760
|
+
}
|
|
761
|
+
const toHostMatch = /^to_host_(\d+)$/.exec(property);
|
|
762
|
+
if (toHostMatch) {
|
|
763
|
+
const signatureId = Number(toHostMatch[1]);
|
|
764
|
+
return (closure: unknown) => {
|
|
765
|
+
const wrapped = (...args: unknown[]) => {
|
|
766
|
+
const instance = instanceCell.instance;
|
|
767
|
+
if (!instance) {
|
|
768
|
+
throw new Error('Closure export wrapper invoked before instantiation completed.');
|
|
769
|
+
}
|
|
770
|
+
const invoke = instance.exports[`__soundscript_closure_invoke_${signatureId}`];
|
|
771
|
+
if (typeof invoke !== 'function') {
|
|
772
|
+
throw new Error(`Missing exported closure invoker for signature ${signatureId}.`);
|
|
773
|
+
}
|
|
774
|
+
return invoke(closure, ...args);
|
|
775
|
+
};
|
|
776
|
+
Object.defineProperty(wrapped, SOUNDSCRIPT_CLOSURE_REF, {
|
|
777
|
+
configurable: true,
|
|
778
|
+
enumerable: false,
|
|
779
|
+
value: closure,
|
|
780
|
+
writable: false,
|
|
781
|
+
});
|
|
782
|
+
return wrapped;
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
return undefined;
|
|
786
|
+
},
|
|
787
|
+
}),
|
|
788
|
+
soundscript_promise: {
|
|
789
|
+
to_internal: (value: unknown, candidate: unknown) => {
|
|
790
|
+
if (!(value instanceof Promise)) {
|
|
791
|
+
throw new TypeError('Expected JS Promise for soundscript_promise.to_internal.');
|
|
792
|
+
}
|
|
793
|
+
const candidateKey = expectHeapIdentityKey(candidate);
|
|
794
|
+
const existing = hostPromiseToInternalCache.get(value);
|
|
795
|
+
if (existing) {
|
|
796
|
+
return existing;
|
|
797
|
+
}
|
|
798
|
+
const instance = instanceCell.instance;
|
|
799
|
+
if (!instance) {
|
|
800
|
+
throw new Error('Promise bridge invoked before instantiation completed.');
|
|
801
|
+
}
|
|
802
|
+
const fulfill = instance.exports.__soundscript_promise_bridge_fulfill;
|
|
803
|
+
const reject = instance.exports.__soundscript_promise_bridge_reject;
|
|
804
|
+
if (typeof fulfill !== 'function' || typeof reject !== 'function') {
|
|
805
|
+
throw new Error('Missing exported Promise bridge helpers.');
|
|
806
|
+
}
|
|
807
|
+
hostPromiseToInternalCache.set(value, candidateKey);
|
|
808
|
+
internalPromiseToHostCache.set(candidateKey, value);
|
|
809
|
+
value.then(
|
|
810
|
+
(resolved) => {
|
|
811
|
+
fulfill(candidateKey, resolved);
|
|
812
|
+
},
|
|
813
|
+
(reason) => {
|
|
814
|
+
reject(candidateKey, reason);
|
|
815
|
+
},
|
|
816
|
+
);
|
|
817
|
+
return candidateKey;
|
|
818
|
+
},
|
|
819
|
+
to_host: (value: unknown) => {
|
|
820
|
+
const internalPromise = expectHeapIdentityKey(value);
|
|
821
|
+
const existing = internalPromiseToHostCache.get(internalPromise);
|
|
822
|
+
if (existing) {
|
|
823
|
+
return existing;
|
|
824
|
+
}
|
|
825
|
+
const instance = instanceCell.instance;
|
|
826
|
+
if (!instance) {
|
|
827
|
+
throw new Error('Promise bridge invoked before instantiation completed.');
|
|
828
|
+
}
|
|
829
|
+
const attach = instance.exports.__soundscript_promise_then_host;
|
|
830
|
+
if (typeof attach !== 'function') {
|
|
831
|
+
throw new Error('Missing exported Promise host attachment helper.');
|
|
832
|
+
}
|
|
833
|
+
const created = new Promise<unknown>((resolve, reject) => {
|
|
834
|
+
attach(internalPromise, resolve, reject);
|
|
835
|
+
});
|
|
836
|
+
internalPromiseToHostCache.set(internalPromise, created);
|
|
837
|
+
return created;
|
|
838
|
+
},
|
|
839
|
+
},
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
export async function instantiateCompiledModuleInJs(
|
|
844
|
+
tempDirectory: string,
|
|
845
|
+
options?: {
|
|
846
|
+
hostFunctions?: Record<string, (...args: unknown[]) => unknown>;
|
|
847
|
+
},
|
|
848
|
+
): Promise<WebAssembly.Instance> {
|
|
849
|
+
const wasmBytes = await readCompiledWasmBytes(tempDirectory);
|
|
850
|
+
return await instantiateSoundscriptWasmModule(wasmBytes, {
|
|
851
|
+
hostFunctions: options?.hostFunctions,
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
export async function readWatArtifactForProject(projectDirectory: string): Promise<string> {
|
|
856
|
+
return await Deno.readTextFile(join(projectDirectory, 'soundscript-out', 'module.wat'));
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
export async function resolveQualifiedExportName(
|
|
860
|
+
tempDirectory: string,
|
|
861
|
+
entry: string,
|
|
862
|
+
): Promise<string> {
|
|
863
|
+
const wat = await readWatArtifact(tempDirectory);
|
|
864
|
+
const exportNames = [...wat.matchAll(/\(export "([^"]+)"\)/g)].map((match) => match[1]);
|
|
865
|
+
|
|
866
|
+
if (exportNames.includes(entry)) {
|
|
867
|
+
return entry;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
const qualifiedMatches = exportNames.filter((name) => name.endsWith(`:${entry}`));
|
|
871
|
+
if (qualifiedMatches.length === 1) {
|
|
872
|
+
return qualifiedMatches[0];
|
|
873
|
+
}
|
|
874
|
+
if (qualifiedMatches.length > 1) {
|
|
875
|
+
throw new Error(`Ambiguous exported function "${entry}".`);
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
throw new Error(`Expected exported function "${entry}".`);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
export async function invokeCompiledEntry(
|
|
882
|
+
tempDirectory: string,
|
|
883
|
+
entry: string,
|
|
884
|
+
args: number[],
|
|
885
|
+
): Promise<number> {
|
|
886
|
+
const exportName = await resolveQualifiedExportName(tempDirectory, entry);
|
|
887
|
+
const instance = await instantiateCompiledModuleInJs(tempDirectory);
|
|
888
|
+
const exported = instance.exports[exportName];
|
|
889
|
+
if (typeof exported !== 'function') {
|
|
890
|
+
throw new Error(`Expected exported function "${exportName}".`);
|
|
891
|
+
}
|
|
892
|
+
const result = exported(...args);
|
|
893
|
+
const value = Number(result);
|
|
894
|
+
if (Number.isNaN(value)) {
|
|
895
|
+
throw new Error(`Expected numeric export result, received "${String(result)}".`);
|
|
896
|
+
}
|
|
897
|
+
return value;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
export function createCompilerProgram(projectPath: string): ts.Program {
|
|
901
|
+
const loadedConfig = loadConfig(projectPath);
|
|
902
|
+
const host = createSoundStdlibCompilerHost(loadedConfig.commandLine.options);
|
|
903
|
+
return ts.createProgram({
|
|
904
|
+
host,
|
|
905
|
+
rootNames: loadedConfig.commandLine.fileNames,
|
|
906
|
+
options: loadedConfig.commandLine.options,
|
|
907
|
+
projectReferences: loadedConfig.commandLine.projectReferences,
|
|
908
|
+
configFileParsingDiagnostics: loadedConfig.diagnostics,
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
export function lowerTempProjectToCompilerIR(tempDirectory: string): CompilerModuleIR {
|
|
913
|
+
const projectPath = join(tempDirectory, 'tsconfig.json');
|
|
914
|
+
const program = createCompilerProgram(projectPath);
|
|
915
|
+
return lowerProgramToCompilerIR(program, dirname(projectPath));
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
export function compileCheckedInProject(relativeProjectDirectory: string) {
|
|
919
|
+
const projectDirectory = join(REPO_ROOT, relativeProjectDirectory);
|
|
920
|
+
return {
|
|
921
|
+
projectDirectory,
|
|
922
|
+
result: compileProject({
|
|
923
|
+
projectPath: join(projectDirectory, 'tsconfig.json'),
|
|
924
|
+
workingDirectory: projectDirectory,
|
|
925
|
+
}),
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
export function lowerCheckedInProjectToCompilerIR(
|
|
930
|
+
relativeProjectDirectory: string,
|
|
931
|
+
): CompilerModuleIR {
|
|
932
|
+
const projectDirectory = join(REPO_ROOT, relativeProjectDirectory);
|
|
933
|
+
const program = createCompilerProgram(join(projectDirectory, 'tsconfig.json'));
|
|
934
|
+
return lowerProgramToCompilerIR(program, projectDirectory);
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
export function getAllRuntimeOperations(moduleIR: CompilerModuleIR) {
|
|
938
|
+
return moduleIR.runtime?.functions.flatMap((runtimeFunction) => runtimeFunction.operations) ?? [];
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
export function assertExecutableOrdinaryObjectLowering(
|
|
942
|
+
moduleIR: CompilerModuleIR,
|
|
943
|
+
options: {
|
|
944
|
+
shapeName: string;
|
|
945
|
+
fieldNames: string[];
|
|
946
|
+
allocationCount: number;
|
|
947
|
+
fieldReadIndices: number[];
|
|
948
|
+
},
|
|
949
|
+
): {
|
|
950
|
+
allocations: CompilerRuntimeAllocateSpecializedObjectIR[];
|
|
951
|
+
fieldReads: CompilerRuntimeGetSpecializedObjectFieldIR[];
|
|
952
|
+
representation: CompilerRuntimeSpecializedObjectRepresentationIR;
|
|
953
|
+
} {
|
|
954
|
+
if (!moduleIR.runtime) {
|
|
955
|
+
throw new Error('Expected lowering to produce runtime IR.');
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
const representation = moduleIR.runtime.representations.find((
|
|
959
|
+
runtimeRepresentation,
|
|
960
|
+
): runtimeRepresentation is CompilerRuntimeSpecializedObjectRepresentationIR =>
|
|
961
|
+
runtimeRepresentation.kind === 'specialized_object_representation' &&
|
|
962
|
+
runtimeRepresentation.name === options.shapeName
|
|
963
|
+
);
|
|
964
|
+
if (!representation) {
|
|
965
|
+
throw new Error(`Expected specialized object representation ${options.shapeName}.`);
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
const operations = getAllRuntimeOperations(moduleIR);
|
|
969
|
+
const allocations = operations.filter((
|
|
970
|
+
operation,
|
|
971
|
+
): operation is CompilerRuntimeAllocateSpecializedObjectIR =>
|
|
972
|
+
operation.kind === 'allocate_specialized_object'
|
|
973
|
+
);
|
|
974
|
+
const fieldReads = operations.filter((
|
|
975
|
+
operation,
|
|
976
|
+
): operation is CompilerRuntimeGetSpecializedObjectFieldIR =>
|
|
977
|
+
operation.kind === 'get_specialized_object_field'
|
|
978
|
+
);
|
|
979
|
+
|
|
980
|
+
assertEquals(
|
|
981
|
+
operations.filter((operation) =>
|
|
982
|
+
operation.kind === 'adapt_value' && operation.family === 'object'
|
|
983
|
+
).length,
|
|
984
|
+
0,
|
|
985
|
+
);
|
|
986
|
+
assertEquals(representation.fields.map((field) => field.name), options.fieldNames);
|
|
987
|
+
assertEquals(allocations.length, options.allocationCount);
|
|
988
|
+
assertEquals(fieldReads.map((operation) => operation.fieldIndex), options.fieldReadIndices);
|
|
989
|
+
assertEquals(
|
|
990
|
+
allocations.every((operation) => operation.representation.name === options.shapeName),
|
|
991
|
+
true,
|
|
992
|
+
);
|
|
993
|
+
assertEquals(
|
|
994
|
+
fieldReads.every((operation) => operation.representation.name === options.shapeName),
|
|
995
|
+
true,
|
|
996
|
+
);
|
|
997
|
+
|
|
998
|
+
return { allocations, fieldReads, representation };
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
export function assertObjectGeneralizationLowering(
|
|
1002
|
+
moduleIR: CompilerModuleIR,
|
|
1003
|
+
options: {
|
|
1004
|
+
shapeName: string;
|
|
1005
|
+
generalizationCount: number;
|
|
1006
|
+
},
|
|
1007
|
+
): {
|
|
1008
|
+
allocations: CompilerRuntimeAllocateSpecializedObjectIR[];
|
|
1009
|
+
generalizations: CompilerRuntimeAdaptObjectValueIR[];
|
|
1010
|
+
representation: CompilerRuntimeSpecializedObjectRepresentationIR;
|
|
1011
|
+
} {
|
|
1012
|
+
if (!moduleIR.runtime) {
|
|
1013
|
+
throw new Error('Expected lowering to produce runtime IR.');
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
const representation = moduleIR.runtime.representations.find((
|
|
1017
|
+
runtimeRepresentation,
|
|
1018
|
+
): runtimeRepresentation is CompilerRuntimeSpecializedObjectRepresentationIR =>
|
|
1019
|
+
runtimeRepresentation.kind === 'specialized_object_representation' &&
|
|
1020
|
+
runtimeRepresentation.name === options.shapeName
|
|
1021
|
+
);
|
|
1022
|
+
if (!representation) {
|
|
1023
|
+
throw new Error(`Expected specialized object representation ${options.shapeName}.`);
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
const operations = getAllRuntimeOperations(moduleIR);
|
|
1027
|
+
const allocations = operations.filter((
|
|
1028
|
+
operation,
|
|
1029
|
+
): operation is CompilerRuntimeAllocateSpecializedObjectIR =>
|
|
1030
|
+
operation.kind === 'allocate_specialized_object'
|
|
1031
|
+
);
|
|
1032
|
+
const generalizations = operations.filter((
|
|
1033
|
+
operation,
|
|
1034
|
+
): operation is CompilerRuntimeAdaptObjectValueIR =>
|
|
1035
|
+
operation.kind === 'adapt_value' && operation.family === 'object'
|
|
1036
|
+
);
|
|
1037
|
+
|
|
1038
|
+
assertEquals(
|
|
1039
|
+
allocations.every((operation) => operation.representation.name === options.shapeName),
|
|
1040
|
+
true,
|
|
1041
|
+
);
|
|
1042
|
+
assertEquals(generalizations.length, options.generalizationCount);
|
|
1043
|
+
assertEquals(
|
|
1044
|
+
generalizations.every((operation) =>
|
|
1045
|
+
operation.fromRepresentation.name === options.shapeName &&
|
|
1046
|
+
operation.toRepresentation.name === 'object.fallback'
|
|
1047
|
+
),
|
|
1048
|
+
true,
|
|
1049
|
+
);
|
|
1050
|
+
|
|
1051
|
+
return { allocations, generalizations, representation };
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
export function assertFallbackObjectRuntimeOperations(moduleIR: CompilerModuleIR): {
|
|
1055
|
+
allocations: CompilerRuntimeAllocateFallbackObjectIR[];
|
|
1056
|
+
generalizations: CompilerRuntimeAdaptObjectValueIR[];
|
|
1057
|
+
propertyGets: CompilerRuntimeGetFallbackObjectPropertyIR[];
|
|
1058
|
+
propertySets: CompilerRuntimeSetFallbackObjectPropertyIR[];
|
|
1059
|
+
} {
|
|
1060
|
+
if (!moduleIR.runtime) {
|
|
1061
|
+
throw new Error('Expected lowering to produce runtime IR.');
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
const operations = getAllRuntimeOperations(moduleIR);
|
|
1065
|
+
return {
|
|
1066
|
+
allocations: operations.filter((
|
|
1067
|
+
operation,
|
|
1068
|
+
): operation is CompilerRuntimeAllocateFallbackObjectIR =>
|
|
1069
|
+
operation.kind === 'allocate_fallback_object'
|
|
1070
|
+
),
|
|
1071
|
+
generalizations: operations.filter((
|
|
1072
|
+
operation,
|
|
1073
|
+
): operation is CompilerRuntimeAdaptObjectValueIR =>
|
|
1074
|
+
operation.kind === 'adapt_value' && operation.family === 'object'
|
|
1075
|
+
),
|
|
1076
|
+
propertyGets: operations.filter((
|
|
1077
|
+
operation,
|
|
1078
|
+
): operation is CompilerRuntimeGetFallbackObjectPropertyIR =>
|
|
1079
|
+
operation.kind === 'get_fallback_object_property'
|
|
1080
|
+
),
|
|
1081
|
+
propertySets: operations.filter((
|
|
1082
|
+
operation,
|
|
1083
|
+
): operation is CompilerRuntimeSetFallbackObjectPropertyIR =>
|
|
1084
|
+
operation.kind === 'set_fallback_object_property'
|
|
1085
|
+
),
|
|
1086
|
+
};
|
|
1087
|
+
}
|