@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.
Files changed (441) hide show
  1. package/package.json +15 -6
  2. package/project-transform/index.js +2 -0
  3. package/project-transform/index.ts +8 -0
  4. package/project-transform/src/annotation_syntax.js +948 -0
  5. package/project-transform/src/annotation_syntax.ts +1217 -0
  6. package/project-transform/src/build_package.js +475 -0
  7. package/project-transform/src/build_package.ts +683 -0
  8. package/project-transform/src/bundled/portable-web-globals.d.ts +153 -0
  9. package/project-transform/src/bundled/runtime_externs.js +220 -0
  10. package/project-transform/src/bundled/runtime_externs.ts +237 -0
  11. package/project-transform/src/bundled/sound-libs/lib.decorators.d.ts +385 -0
  12. package/project-transform/src/bundled/sound-libs/lib.decorators.legacy.d.ts +22 -0
  13. package/project-transform/src/bundled/sound-libs/lib.dom.asynciterable.d.ts +42 -0
  14. package/project-transform/src/bundled/sound-libs/lib.dom.d.ts +39440 -0
  15. package/project-transform/src/bundled/sound-libs/lib.es2015.collection.d.ts +149 -0
  16. package/project-transform/src/bundled/sound-libs/lib.es2015.core.d.ts +657 -0
  17. package/project-transform/src/bundled/sound-libs/lib.es2015.d.ts +28 -0
  18. package/project-transform/src/bundled/sound-libs/lib.es2015.generator.d.ts +77 -0
  19. package/project-transform/src/bundled/sound-libs/lib.es2015.iterable.d.ts +616 -0
  20. package/project-transform/src/bundled/sound-libs/lib.es2015.promise.d.ts +80 -0
  21. package/project-transform/src/bundled/sound-libs/lib.es2015.proxy.d.ts +128 -0
  22. package/project-transform/src/bundled/sound-libs/lib.es2015.reflect.d.ts +144 -0
  23. package/project-transform/src/bundled/sound-libs/lib.es2015.symbol.d.ts +46 -0
  24. package/project-transform/src/bundled/sound-libs/lib.es2015.symbol.wellknown.d.ts +170 -0
  25. package/project-transform/src/bundled/sound-libs/lib.es2016.array.include.d.ts +116 -0
  26. package/project-transform/src/bundled/sound-libs/lib.es2016.d.ts +21 -0
  27. package/project-transform/src/bundled/sound-libs/lib.es2017.arraybuffer.d.ts +21 -0
  28. package/project-transform/src/bundled/sound-libs/lib.es2017.d.ts +26 -0
  29. package/project-transform/src/bundled/sound-libs/lib.es2017.date.d.ts +31 -0
  30. package/project-transform/src/bundled/sound-libs/lib.es2017.object.d.ts +49 -0
  31. package/project-transform/src/bundled/sound-libs/lib.es2017.string.d.ts +45 -0
  32. package/project-transform/src/bundled/sound-libs/lib.es2017.typedarrays.d.ts +53 -0
  33. package/project-transform/src/bundled/sound-libs/lib.es2018.asyncgenerator.d.ts +77 -0
  34. package/project-transform/src/bundled/sound-libs/lib.es2018.asynciterable.d.ts +57 -0
  35. package/project-transform/src/bundled/sound-libs/lib.es2018.d.ts +24 -0
  36. package/project-transform/src/bundled/sound-libs/lib.es2018.promise.d.ts +30 -0
  37. package/project-transform/src/bundled/sound-libs/lib.es2018.regexp.d.ts +37 -0
  38. package/project-transform/src/bundled/sound-libs/lib.es2019.array.d.ts +79 -0
  39. package/project-transform/src/bundled/sound-libs/lib.es2019.d.ts +24 -0
  40. package/project-transform/src/bundled/sound-libs/lib.es2019.object.d.ts +47 -0
  41. package/project-transform/src/bundled/sound-libs/lib.es2019.string.d.ts +37 -0
  42. package/project-transform/src/bundled/sound-libs/lib.es2019.symbol.d.ts +24 -0
  43. package/project-transform/src/bundled/sound-libs/lib.es2020.bigint.d.ts +765 -0
  44. package/project-transform/src/bundled/sound-libs/lib.es2020.d.ts +27 -0
  45. package/project-transform/src/bundled/sound-libs/lib.es2020.date.d.ts +42 -0
  46. package/project-transform/src/bundled/sound-libs/lib.es2020.number.d.ts +28 -0
  47. package/project-transform/src/bundled/sound-libs/lib.es2020.promise.d.ts +49 -0
  48. package/project-transform/src/bundled/sound-libs/lib.es2020.string.d.ts +44 -0
  49. package/project-transform/src/bundled/sound-libs/lib.es2020.symbol.wellknown.d.ts +41 -0
  50. package/project-transform/src/bundled/sound-libs/lib.es2021.d.ts +23 -0
  51. package/project-transform/src/bundled/sound-libs/lib.es2021.promise.d.ts +48 -0
  52. package/project-transform/src/bundled/sound-libs/lib.es2021.string.d.ts +33 -0
  53. package/project-transform/src/bundled/sound-libs/lib.es2021.weakref.d.ts +78 -0
  54. package/project-transform/src/bundled/sound-libs/lib.es2022.array.d.ts +121 -0
  55. package/project-transform/src/bundled/sound-libs/lib.es2022.d.ts +25 -0
  56. package/project-transform/src/bundled/sound-libs/lib.es2022.error.d.ts +75 -0
  57. package/project-transform/src/bundled/sound-libs/lib.es2022.object.d.ts +26 -0
  58. package/project-transform/src/bundled/sound-libs/lib.es2022.regexp.d.ts +39 -0
  59. package/project-transform/src/bundled/sound-libs/lib.es2022.string.d.ts +25 -0
  60. package/project-transform/src/bundled/sound-libs/lib.es2023.array.d.ts +924 -0
  61. package/project-transform/src/bundled/sound-libs/lib.es2023.collection.d.ts +21 -0
  62. package/project-transform/src/bundled/sound-libs/lib.es2023.d.ts +22 -0
  63. package/project-transform/src/bundled/sound-libs/lib.es2024.arraybuffer.d.ts +65 -0
  64. package/project-transform/src/bundled/sound-libs/lib.es2024.collection.d.ts +29 -0
  65. package/project-transform/src/bundled/sound-libs/lib.es2024.d.ts +26 -0
  66. package/project-transform/src/bundled/sound-libs/lib.es2024.object.d.ts +33 -0
  67. package/project-transform/src/bundled/sound-libs/lib.es2024.promise.d.ts +35 -0
  68. package/project-transform/src/bundled/sound-libs/lib.es2024.regexp.d.ts +25 -0
  69. package/project-transform/src/bundled/sound-libs/lib.es2024.string.d.ts +29 -0
  70. package/project-transform/src/bundled/sound-libs/lib.es5.d.ts +4924 -0
  71. package/project-transform/src/bundled/sound_stdlib.js +142 -0
  72. package/project-transform/src/bundled/sound_stdlib.ts +180 -0
  73. package/project-transform/src/checker/analyze_project.js +1361 -0
  74. package/project-transform/src/checker/analyze_project.ts +2246 -0
  75. package/project-transform/src/checker/diagnostics.js +112 -0
  76. package/project-transform/src/checker/diagnostics.ts +222 -0
  77. package/project-transform/src/checker/engine/context.js +235 -0
  78. package/project-transform/src/checker/engine/context.ts +340 -0
  79. package/project-transform/src/checker/engine/diagnostic_codes.js +72 -0
  80. package/project-transform/src/checker/engine/diagnostic_codes.ts +95 -0
  81. package/project-transform/src/checker/engine/facts.js +35 -0
  82. package/project-transform/src/checker/engine/facts.ts +48 -0
  83. package/project-transform/src/checker/engine/types.js +1 -0
  84. package/project-transform/src/checker/engine/types.ts +485 -0
  85. package/project-transform/src/checker/proof_escape_hatch_diagnostics.js +104 -0
  86. package/project-transform/src/checker/proof_escape_hatch_diagnostics.ts +173 -0
  87. package/project-transform/src/checker/rules/async_surface.js +231 -0
  88. package/project-transform/src/checker/rules/async_surface.ts +335 -0
  89. package/project-transform/src/checker/rules/class_lifecycle.js +798 -0
  90. package/project-transform/src/checker/rules/class_lifecycle.ts +1276 -0
  91. package/project-transform/src/checker/rules/directive_validation.js +571 -0
  92. package/project-transform/src/checker/rules/directive_validation.ts +938 -0
  93. package/project-transform/src/checker/rules/directives.js +23 -0
  94. package/project-transform/src/checker/rules/directives.ts +25 -0
  95. package/project-transform/src/checker/rules/flow.js +202 -0
  96. package/project-transform/src/checker/rules/flow.ts +333 -0
  97. package/project-transform/src/checker/rules/flow_facts.js +601 -0
  98. package/project-transform/src/checker/rules/flow_facts.ts +978 -0
  99. package/project-transform/src/checker/rules/flow_invalidation.js +1119 -0
  100. package/project-transform/src/checker/rules/flow_invalidation.ts +2150 -0
  101. package/project-transform/src/checker/rules/flow_shared.js +2822 -0
  102. package/project-transform/src/checker/rules/flow_shared.ts +4383 -0
  103. package/project-transform/src/checker/rules/foreign_boundary.js +120 -0
  104. package/project-transform/src/checker/rules/foreign_boundary.ts +196 -0
  105. package/project-transform/src/checker/rules/foreign_projection.js +279 -0
  106. package/project-transform/src/checker/rules/foreign_projection.ts +425 -0
  107. package/project-transform/src/checker/rules/generated_helpers.js +13 -0
  108. package/project-transform/src/checker/rules/generated_helpers.ts +18 -0
  109. package/project-transform/src/checker/rules/index.js +35 -0
  110. package/project-transform/src/checker/rules/index.ts +49 -0
  111. package/project-transform/src/checker/rules/namespace_object.js +845 -0
  112. package/project-transform/src/checker/rules/namespace_object.ts +1224 -0
  113. package/project-transform/src/checker/rules/non_ordinary_recovery.js +1328 -0
  114. package/project-transform/src/checker/rules/non_ordinary_recovery.ts +2391 -0
  115. package/project-transform/src/checker/rules/null_prototype.js +3 -0
  116. package/project-transform/src/checker/rules/null_prototype.ts +6 -0
  117. package/project-transform/src/checker/rules/overloads.js +181 -0
  118. package/project-transform/src/checker/rules/overloads.ts +317 -0
  119. package/project-transform/src/checker/rules/predicate_verification.js +691 -0
  120. package/project-transform/src/checker/rules/predicate_verification.ts +1088 -0
  121. package/project-transform/src/checker/rules/prototype_hardening.js +237 -0
  122. package/project-transform/src/checker/rules/prototype_hardening.ts +343 -0
  123. package/project-transform/src/checker/rules/receiver_discipline.js +263 -0
  124. package/project-transform/src/checker/rules/receiver_discipline.ts +356 -0
  125. package/project-transform/src/checker/rules/relations.js +6861 -0
  126. package/project-transform/src/checker/rules/relations.ts +12158 -0
  127. package/project-transform/src/checker/rules/resolved_builtins.js +274 -0
  128. package/project-transform/src/checker/rules/resolved_builtins.ts +438 -0
  129. package/project-transform/src/checker/rules/trust.js +217 -0
  130. package/project-transform/src/checker/rules/trust.ts +301 -0
  131. package/project-transform/src/checker/rules/type_guards.js +173 -0
  132. package/project-transform/src/checker/rules/type_guards.ts +257 -0
  133. package/project-transform/src/checker/rules/universal.js +17 -0
  134. package/project-transform/src/checker/rules/universal.ts +22 -0
  135. package/project-transform/src/checker/rules/unsafe_value_origin.js +80 -0
  136. package/project-transform/src/checker/rules/unsafe_value_origin.ts +125 -0
  137. package/project-transform/src/checker/rules/unsound_imports.js +218 -0
  138. package/project-transform/src/checker/rules/unsound_imports.ts +301 -0
  139. package/project-transform/src/checker/rules/unsound_syntax.js +1695 -0
  140. package/project-transform/src/checker/rules/unsound_syntax.ts +2540 -0
  141. package/project-transform/src/checker/rules/value_types.js +206 -0
  142. package/project-transform/src/checker/rules/value_types.ts +407 -0
  143. package/project-transform/src/checker/timing.js +43 -0
  144. package/project-transform/src/checker/timing.ts +78 -0
  145. package/project-transform/src/checker/unsupported_feature_messages.js +337 -0
  146. package/project-transform/src/checker/unsupported_feature_messages.ts +531 -0
  147. package/project-transform/src/cli.js +892 -0
  148. package/project-transform/src/cli.ts +1476 -0
  149. package/project-transform/src/compiler/compile_project.js +319 -0
  150. package/project-transform/src/compiler/compile_project.ts +508 -0
  151. package/project-transform/src/compiler/errors.js +10 -0
  152. package/project-transform/src/compiler/errors.ts +29 -0
  153. package/project-transform/src/compiler/ir.js +1 -0
  154. package/project-transform/src/compiler/ir.ts +1526 -0
  155. package/project-transform/src/compiler/lower.js +30550 -0
  156. package/project-transform/src/compiler/lower.ts +43645 -0
  157. package/project-transform/src/compiler/lower_arrays.js +140 -0
  158. package/project-transform/src/compiler/lower_arrays.ts +190 -0
  159. package/project-transform/src/compiler/lower_strings.js +121 -0
  160. package/project-transform/src/compiler/lower_strings.ts +198 -0
  161. package/project-transform/src/compiler/lower_tagged.js +329 -0
  162. package/project-transform/src/compiler/lower_tagged.ts +427 -0
  163. package/project-transform/src/compiler/lower_views.js +171 -0
  164. package/project-transform/src/compiler/lower_views.ts +251 -0
  165. package/project-transform/src/compiler/object_keys.js +25 -0
  166. package/project-transform/src/compiler/object_keys.ts +35 -0
  167. package/project-transform/src/compiler/runtime_ir.js +30 -0
  168. package/project-transform/src/compiler/runtime_ir.ts +727 -0
  169. package/project-transform/src/compiler/tagged_boundary.js +18 -0
  170. package/project-transform/src/compiler/tagged_boundary.ts +37 -0
  171. package/project-transform/src/compiler/toolchain.js +170 -0
  172. package/project-transform/src/compiler/toolchain.ts +229 -0
  173. package/project-transform/src/compiler/unicode_case_data.js +2102 -0
  174. package/project-transform/src/compiler/unicode_case_data.ts +2112 -0
  175. package/project-transform/src/compiler/wasm_js_host_runtime.js +656 -0
  176. package/project-transform/src/compiler/wasm_js_host_runtime.ts +762 -0
  177. package/project-transform/src/compiler/wat_arrays.js +3132 -0
  178. package/project-transform/src/compiler/wat_arrays.ts +3768 -0
  179. package/project-transform/src/compiler/wat_emitter.js +17952 -0
  180. package/project-transform/src/compiler/wat_emitter.ts +22812 -0
  181. package/project-transform/src/compiler/wat_strings.js +129 -0
  182. package/project-transform/src/compiler/wat_strings.ts +187 -0
  183. package/project-transform/src/compiler/wat_tagged.js +548 -0
  184. package/project-transform/src/compiler/wat_tagged.ts +674 -0
  185. package/project-transform/src/compiler_generator_runner.js +153 -0
  186. package/project-transform/src/compiler_generator_runner.ts +171 -0
  187. package/project-transform/src/compiler_object_test_helpers.js +69 -0
  188. package/project-transform/src/compiler_object_test_helpers.ts +96 -0
  189. package/project-transform/src/compiler_promise_runner.js +2116 -0
  190. package/project-transform/src/compiler_promise_runner.ts +2184 -0
  191. package/project-transform/src/compiler_test_helpers.js +854 -0
  192. package/project-transform/src/compiler_test_helpers.ts +1087 -0
  193. package/project-transform/src/config.js +568 -0
  194. package/project-transform/src/config.ts +892 -0
  195. package/project-transform/src/diagnostic_metadata.js +67 -0
  196. package/project-transform/src/diagnostic_metadata.ts +99 -0
  197. package/project-transform/src/diagnostic_reference.js +1368 -0
  198. package/project-transform/src/diagnostic_reference.ts +1523 -0
  199. package/project-transform/src/editor_diagnostics_worker.js +176 -0
  200. package/project-transform/src/editor_diagnostics_worker.ts +250 -0
  201. package/project-transform/src/editor_projection.js +224 -0
  202. package/project-transform/src/editor_projection.ts +421 -0
  203. package/project-transform/src/frontend/builtin_expanded_program_test_cleanup.js +47 -0
  204. package/project-transform/src/frontend/builtin_expanded_program_test_cleanup.ts +72 -0
  205. package/project-transform/src/frontend/builtin_macro_support.js +842 -0
  206. package/project-transform/src/frontend/builtin_macro_support.ts +1386 -0
  207. package/project-transform/src/frontend/builtin_macros.js +409 -0
  208. package/project-transform/src/frontend/builtin_macros.ts +542 -0
  209. package/project-transform/src/frontend/component_poc_runtime.js +279 -0
  210. package/project-transform/src/frontend/component_poc_runtime.ts +372 -0
  211. package/project-transform/src/frontend/css_macro.js +148 -0
  212. package/project-transform/src/frontend/css_macro.ts +222 -0
  213. package/project-transform/src/frontend/derive_macros.js +2072 -0
  214. package/project-transform/src/frontend/derive_macros.ts +3188 -0
  215. package/project-transform/src/frontend/embedded_fragment_support.js +106 -0
  216. package/project-transform/src/frontend/embedded_fragment_support.ts +172 -0
  217. package/project-transform/src/frontend/error_normalization.js +403 -0
  218. package/project-transform/src/frontend/error_normalization.ts +832 -0
  219. package/project-transform/src/frontend/error_stdlib_support.js +1 -0
  220. package/project-transform/src/frontend/error_stdlib_support.ts +6 -0
  221. package/project-transform/src/frontend/expand_project.js +169 -0
  222. package/project-transform/src/frontend/expand_project.ts +248 -0
  223. package/project-transform/src/frontend/format_soundscript.js +297 -0
  224. package/project-transform/src/frontend/format_soundscript.ts +582 -0
  225. package/project-transform/src/frontend/graphql_macro.js +174 -0
  226. package/project-transform/src/frontend/graphql_macro.ts +253 -0
  227. package/project-transform/src/frontend/hash_context.js +83 -0
  228. package/project-transform/src/frontend/hash_context.ts +113 -0
  229. package/project-transform/src/frontend/hkt_macro.js +448 -0
  230. package/project-transform/src/frontend/hkt_macro.ts +897 -0
  231. package/project-transform/src/frontend/import_binding_usage.js +190 -0
  232. package/project-transform/src/frontend/import_binding_usage.ts +277 -0
  233. package/project-transform/src/frontend/macro_advanced_backend_adapter.js +58 -0
  234. package/project-transform/src/frontend/macro_advanced_backend_adapter.ts +123 -0
  235. package/project-transform/src/frontend/macro_advanced_context.js +826 -0
  236. package/project-transform/src/frontend/macro_advanced_context.ts +1102 -0
  237. package/project-transform/src/frontend/macro_advanced_output.js +21 -0
  238. package/project-transform/src/frontend/macro_advanced_output.ts +41 -0
  239. package/project-transform/src/frontend/macro_api.js +353 -0
  240. package/project-transform/src/frontend/macro_api.ts +1722 -0
  241. package/project-transform/src/frontend/macro_api_internal.js +35 -0
  242. package/project-transform/src/frontend/macro_api_internal.ts +80 -0
  243. package/project-transform/src/frontend/macro_api_module_support.js +39 -0
  244. package/project-transform/src/frontend/macro_api_module_support.ts +65 -0
  245. package/project-transform/src/frontend/macro_backend_adapter.js +272 -0
  246. package/project-transform/src/frontend/macro_backend_adapter.ts +420 -0
  247. package/project-transform/src/frontend/macro_context.js +816 -0
  248. package/project-transform/src/frontend/macro_context.ts +1105 -0
  249. package/project-transform/src/frontend/macro_debug.js +99 -0
  250. package/project-transform/src/frontend/macro_debug.ts +157 -0
  251. package/project-transform/src/frontend/macro_definition_support.js +28 -0
  252. package/project-transform/src/frontend/macro_definition_support.ts +73 -0
  253. package/project-transform/src/frontend/macro_errors.js +40 -0
  254. package/project-transform/src/frontend/macro_errors.ts +70 -0
  255. package/project-transform/src/frontend/macro_expander.js +919 -0
  256. package/project-transform/src/frontend/macro_expander.ts +1611 -0
  257. package/project-transform/src/frontend/macro_factory_support.js +176 -0
  258. package/project-transform/src/frontend/macro_factory_support.ts +263 -0
  259. package/project-transform/src/frontend/macro_host_ast_internal.js +64 -0
  260. package/project-transform/src/frontend/macro_host_ast_internal.ts +109 -0
  261. package/project-transform/src/frontend/macro_index.js +27 -0
  262. package/project-transform/src/frontend/macro_index.ts +50 -0
  263. package/project-transform/src/frontend/macro_loader.js +281 -0
  264. package/project-transform/src/frontend/macro_loader.ts +506 -0
  265. package/project-transform/src/frontend/macro_operand_semantics.js +838 -0
  266. package/project-transform/src/frontend/macro_operand_semantics.ts +1489 -0
  267. package/project-transform/src/frontend/macro_output.js +54 -0
  268. package/project-transform/src/frontend/macro_output.ts +123 -0
  269. package/project-transform/src/frontend/macro_parser.js +611 -0
  270. package/project-transform/src/frontend/macro_parser.ts +832 -0
  271. package/project-transform/src/frontend/macro_resolver.js +69 -0
  272. package/project-transform/src/frontend/macro_resolver.ts +125 -0
  273. package/project-transform/src/frontend/macro_rewrite.js +285 -0
  274. package/project-transform/src/frontend/macro_rewrite.ts +442 -0
  275. package/project-transform/src/frontend/macro_runtime_support.js +232 -0
  276. package/project-transform/src/frontend/macro_runtime_support.ts +324 -0
  277. package/project-transform/src/frontend/macro_scanner.js +393 -0
  278. package/project-transform/src/frontend/macro_scanner.ts +455 -0
  279. package/project-transform/src/frontend/macro_semantic_backend_adapter.js +87 -0
  280. package/project-transform/src/frontend/macro_semantic_backend_adapter.ts +166 -0
  281. package/project-transform/src/frontend/macro_semantic_context.js +5 -0
  282. package/project-transform/src/frontend/macro_semantic_context.ts +12 -0
  283. package/project-transform/src/frontend/macro_semantic_output.js +24 -0
  284. package/project-transform/src/frontend/macro_semantic_output.ts +47 -0
  285. package/project-transform/src/frontend/macro_semantic_types.js +1 -0
  286. package/project-transform/src/frontend/macro_semantic_types.ts +98 -0
  287. package/project-transform/src/frontend/macro_semantics.js +1172 -0
  288. package/project-transform/src/frontend/macro_semantics.ts +1502 -0
  289. package/project-transform/src/frontend/macro_site_kind_support.js +164 -0
  290. package/project-transform/src/frontend/macro_site_kind_support.ts +255 -0
  291. package/project-transform/src/frontend/macro_syntax_internal.js +1950 -0
  292. package/project-transform/src/frontend/macro_syntax_internal.ts +3338 -0
  293. package/project-transform/src/frontend/macro_templates.js +57 -0
  294. package/project-transform/src/frontend/macro_templates.ts +143 -0
  295. package/project-transform/src/frontend/macro_test_helpers.js +82 -0
  296. package/project-transform/src/frontend/macro_test_helpers.ts +136 -0
  297. package/project-transform/src/frontend/macro_types.js +1 -0
  298. package/project-transform/src/frontend/macro_types.ts +103 -0
  299. package/project-transform/src/frontend/macro_vm.js +39 -0
  300. package/project-transform/src/frontend/macro_vm.ts +113 -0
  301. package/project-transform/src/frontend/match_macro.js +885 -0
  302. package/project-transform/src/frontend/match_macro.ts +1220 -0
  303. package/project-transform/src/frontend/numeric_normalization.js +824 -0
  304. package/project-transform/src/frontend/numeric_normalization.ts +1380 -0
  305. package/project-transform/src/frontend/numeric_prelude.js +278 -0
  306. package/project-transform/src/frontend/numeric_prelude.ts +370 -0
  307. package/project-transform/src/frontend/project_frontend.js +2396 -0
  308. package/project-transform/src/frontend/project_frontend.ts +3776 -0
  309. package/project-transform/src/frontend/project_macro_support.js +1401 -0
  310. package/project-transform/src/frontend/project_macro_support.ts +2137 -0
  311. package/project-transform/src/frontend/sql_macro.js +175 -0
  312. package/project-transform/src/frontend/sql_macro.ts +254 -0
  313. package/project-transform/src/frontend/sql_stdlib_support.js +1 -0
  314. package/project-transform/src/frontend/sql_stdlib_support.ts +6 -0
  315. package/project-transform/src/frontend/std_package_support.js +228 -0
  316. package/project-transform/src/frontend/std_package_support.ts +400 -0
  317. package/project-transform/src/frontend/value_normalization.js +306 -0
  318. package/project-transform/src/frontend/value_normalization.ts +599 -0
  319. package/project-transform/src/lsp/project_service.js +4771 -0
  320. package/project-transform/src/lsp/project_service.ts +7580 -0
  321. package/project-transform/src/lsp/protocol.js +9 -0
  322. package/project-transform/src/lsp/protocol.ts +38 -0
  323. package/project-transform/src/lsp/server.js +355 -0
  324. package/project-transform/src/lsp/server.ts +671 -0
  325. package/project-transform/src/lsp/session.js +49 -0
  326. package/project-transform/src/lsp/session.ts +48 -0
  327. package/project-transform/src/lsp/timing.js +43 -0
  328. package/project-transform/src/lsp/timing.ts +76 -0
  329. package/project-transform/src/lsp/transport.js +205 -0
  330. package/project-transform/src/lsp/transport.ts +253 -0
  331. package/project-transform/src/lsp_main.js +5 -0
  332. package/project-transform/src/lsp_main.ts +7 -0
  333. package/project-transform/src/macros.d.ts +1 -0
  334. package/project-transform/src/macros.js +1 -0
  335. package/project-transform/src/macros.ts +1 -0
  336. package/project-transform/src/main.js +24 -0
  337. package/project-transform/src/main.ts +28 -0
  338. package/project-transform/src/platform/host.js +264 -0
  339. package/project-transform/src/platform/host.ts +343 -0
  340. package/project-transform/src/platform/path.js +8 -0
  341. package/project-transform/src/platform/path.ts +20 -0
  342. package/project-transform/src/public_macro_api/macro_api.d.ts +1054 -0
  343. package/project-transform/src/public_macro_api/macro_semantic_types.d.ts +66 -0
  344. package/project-transform/src/public_macro_api/macro_types.d.ts +70 -0
  345. package/project-transform/src/run_program.js +14 -0
  346. package/project-transform/src/run_program.ts +33 -0
  347. package/project-transform/src/runtime/materialize.js +371 -0
  348. package/project-transform/src/runtime/materialize.ts +502 -0
  349. package/project-transform/src/runtime/on_demand.js +203 -0
  350. package/project-transform/src/runtime/on_demand.ts +305 -0
  351. package/project-transform/src/runtime/source_maps.js +205 -0
  352. package/project-transform/src/runtime/source_maps.ts +297 -0
  353. package/project-transform/src/runtime/transform.js +148 -0
  354. package/project-transform/src/runtime/transform.ts +295 -0
  355. package/project-transform/src/service/types.js +1 -0
  356. package/project-transform/src/service/types.ts +22 -0
  357. package/project-transform/src/soundscript_packages.js +477 -0
  358. package/project-transform/src/soundscript_packages.ts +754 -0
  359. package/project-transform/src/soundscript_runtime_specifiers.js +88 -0
  360. package/project-transform/src/soundscript_runtime_specifiers.ts +96 -0
  361. package/project-transform/src/stdlib/async.d.ts +81 -0
  362. package/project-transform/src/stdlib/async.js +213 -0
  363. package/project-transform/src/stdlib/async.ts +315 -0
  364. package/project-transform/src/stdlib/codec.d.ts +32 -0
  365. package/project-transform/src/stdlib/codec.js +30 -0
  366. package/project-transform/src/stdlib/codec.ts +76 -0
  367. package/project-transform/src/stdlib/compare.d.ts +28 -0
  368. package/project-transform/src/stdlib/compare.js +115 -0
  369. package/project-transform/src/stdlib/compare.ts +151 -0
  370. package/project-transform/src/stdlib/css.d.ts +16 -0
  371. package/project-transform/src/stdlib/css.js +9 -0
  372. package/project-transform/src/stdlib/css.ts +28 -0
  373. package/project-transform/src/stdlib/debug.d.ts +2 -0
  374. package/project-transform/src/stdlib/debug.js +9 -0
  375. package/project-transform/src/stdlib/debug.ts +10 -0
  376. package/project-transform/src/stdlib/decode.d.ts +86 -0
  377. package/project-transform/src/stdlib/decode.js +254 -0
  378. package/project-transform/src/stdlib/decode.ts +390 -0
  379. package/project-transform/src/stdlib/derive.d.ts +6 -0
  380. package/project-transform/src/stdlib/derive.js +7 -0
  381. package/project-transform/src/stdlib/derive.ts +7 -0
  382. package/project-transform/src/stdlib/encode.d.ts +100 -0
  383. package/project-transform/src/stdlib/encode.js +130 -0
  384. package/project-transform/src/stdlib/encode.ts +259 -0
  385. package/project-transform/src/stdlib/failures.d.ts +23 -0
  386. package/project-transform/src/stdlib/failures.js +41 -0
  387. package/project-transform/src/stdlib/failures.ts +64 -0
  388. package/project-transform/src/stdlib/fetch.d.ts +67 -0
  389. package/project-transform/src/stdlib/fetch.js +5 -0
  390. package/project-transform/src/stdlib/fetch.ts +11 -0
  391. package/project-transform/src/stdlib/graphql.d.ts +16 -0
  392. package/project-transform/src/stdlib/graphql.js +9 -0
  393. package/project-transform/src/stdlib/graphql.ts +28 -0
  394. package/project-transform/src/stdlib/hash.d.ts +34 -0
  395. package/project-transform/src/stdlib/hash.js +110 -0
  396. package/project-transform/src/stdlib/hash.ts +188 -0
  397. package/project-transform/src/stdlib/hkt.d.ts +40 -0
  398. package/project-transform/src/stdlib/hkt.js +3 -0
  399. package/project-transform/src/stdlib/hkt.ts +41 -0
  400. package/project-transform/src/stdlib/index.d.ts +9 -0
  401. package/project-transform/src/stdlib/index.js +15 -0
  402. package/project-transform/src/stdlib/index.ts +23 -0
  403. package/project-transform/src/stdlib/json.d.ts +125 -0
  404. package/project-transform/src/stdlib/json.js +764 -0
  405. package/project-transform/src/stdlib/json.ts +1034 -0
  406. package/project-transform/src/stdlib/match.d.ts +11 -0
  407. package/project-transform/src/stdlib/match.js +13 -0
  408. package/project-transform/src/stdlib/match.ts +26 -0
  409. package/project-transform/src/stdlib/numerics.d.ts +523 -0
  410. package/project-transform/src/stdlib/numerics.js +1356 -0
  411. package/project-transform/src/stdlib/numerics.ts +1937 -0
  412. package/project-transform/src/stdlib/random.d.ts +19 -0
  413. package/project-transform/src/stdlib/random.js +3 -0
  414. package/project-transform/src/stdlib/random.ts +5 -0
  415. package/project-transform/src/stdlib/result.d.ts +68 -0
  416. package/project-transform/src/stdlib/result.js +139 -0
  417. package/project-transform/src/stdlib/result.ts +248 -0
  418. package/project-transform/src/stdlib/sql.d.ts +22 -0
  419. package/project-transform/src/stdlib/sql.js +23 -0
  420. package/project-transform/src/stdlib/sql.ts +53 -0
  421. package/project-transform/src/stdlib/text.d.ts +24 -0
  422. package/project-transform/src/stdlib/text.js +3 -0
  423. package/project-transform/src/stdlib/text.ts +4 -0
  424. package/project-transform/src/stdlib/thunk.d.ts +2 -0
  425. package/project-transform/src/stdlib/thunk.js +9 -0
  426. package/project-transform/src/stdlib/thunk.ts +15 -0
  427. package/project-transform/src/stdlib/typeclasses.d.ts +57 -0
  428. package/project-transform/src/stdlib/typeclasses.js +78 -0
  429. package/project-transform/src/stdlib/typeclasses.ts +173 -0
  430. package/project-transform/src/stdlib/url.d.ts +37 -0
  431. package/project-transform/src/stdlib/url.js +3 -0
  432. package/project-transform/src/stdlib/url.ts +4 -0
  433. package/project-transform/src/stdlib/value.d.ts +9 -0
  434. package/project-transform/src/stdlib/value.js +104 -0
  435. package/project-transform/src/stdlib/value.ts +133 -0
  436. package/project-transform/src/test_installed_stdlib.js +147 -0
  437. package/project-transform/src/test_installed_stdlib.ts +245 -0
  438. package/project-transform/src/test_macro_package_fixture.js +50 -0
  439. package/project-transform/src/test_macro_package_fixture.ts +68 -0
  440. package/project-transform/src/value_deep_safe.js +191 -0
  441. package/project-transform/src/value_deep_safe.ts +273 -0
@@ -0,0 +1,2184 @@
1
+ import { assertEquals } from '@std/assert';
2
+
3
+ import { compileTempProject, createCompilerTestProject } from './compiler_object_test_helpers.ts';
4
+ import {
5
+ instantiateCompiledModuleInJs,
6
+ resolveQualifiedExportName,
7
+ } from './compiler_test_helpers.ts';
8
+
9
+ type PromiseCompilerCase = {
10
+ name: string;
11
+ source: string;
12
+ expectedObserved?: number;
13
+ hostFunctions?: Record<string, (...args: unknown[]) => unknown>;
14
+ reducer?: 'last' | 'weighted';
15
+ run?: (exported: (...args: unknown[]) => unknown) => Promise<void>;
16
+ };
17
+
18
+ async function runPromiseCompilerCase(testCase: PromiseCompilerCase): Promise<void> {
19
+ const tempDirectory = await createCompilerTestProject(testCase.source);
20
+ const result = compileTempProject(tempDirectory);
21
+
22
+ assertEquals(result.exitCode, 0, testCase.name);
23
+ assertEquals(result.diagnostics, [], testCase.name);
24
+ const instance = await instantiateCompiledModuleInJs(tempDirectory, {
25
+ hostFunctions: testCase.hostFunctions,
26
+ });
27
+ const exportName = await resolveQualifiedExportName(tempDirectory, 'main');
28
+ const exported = instance.exports[exportName];
29
+ if (typeof exported !== 'function') {
30
+ throw new Error(`Expected exported function "${exportName}" for ${testCase.name}.`);
31
+ }
32
+ if (testCase.run) {
33
+ await testCase.run(exported as (...args: unknown[]) => unknown);
34
+ return;
35
+ }
36
+ let observed = 0;
37
+ if (testCase.expectedObserved === undefined || !testCase.reducer) {
38
+ throw new Error(`Missing callback expectations for ${testCase.name}.`);
39
+ }
40
+ assertEquals(
41
+ exported((value: number) => {
42
+ observed = testCase.reducer === 'weighted' ? observed * 100 + value : value;
43
+ return value;
44
+ }),
45
+ 0,
46
+ testCase.name,
47
+ );
48
+ assertEquals(observed, testCase.expectedObserved, testCase.name);
49
+ }
50
+
51
+ async function main(): Promise<void> {
52
+ const caseFilter = Deno.env.get('SOUNDSCRIPT_PROMISE_CASE');
53
+ const caseFiltersValue = Deno.env.get('SOUNDSCRIPT_PROMISE_CASES');
54
+ const caseFilters = caseFiltersValue ? new Set(JSON.parse(caseFiltersValue) as string[]) : undefined;
55
+ const cases: PromiseCompilerCase[] = [
56
+ {
57
+ name: 'compileProject executes Promise.all over direct fulfilled Promise array literals',
58
+ expectedObserved: 22,
59
+ reducer: 'last',
60
+ source: [
61
+ 'export function main(callback: (value: number) => number): number {',
62
+ ' Promise.all([Promise.resolve(20), Promise.resolve(2)])',
63
+ ' .then((values) => {',
64
+ ' callback(values[0] + values[1]);',
65
+ ' return values.length;',
66
+ ' });',
67
+ ' return 0;',
68
+ '}',
69
+ '',
70
+ ].join('\n'),
71
+ },
72
+ {
73
+ name: 'compileProject propagates Promise.all rejections from direct Promise array literals',
74
+ expectedObserved: 23,
75
+ reducer: 'last',
76
+ source: [
77
+ 'export function main(callback: (value: number) => number): number {',
78
+ ' Promise.all([Promise.resolve(20), Promise.reject<number>(2)])',
79
+ ' .catch(() => {',
80
+ ' callback(23);',
81
+ ' return 0;',
82
+ ' });',
83
+ ' return 0;',
84
+ '}',
85
+ '',
86
+ ].join('\n'),
87
+ },
88
+ {
89
+ name: 'compileProject executes Promise.race over direct fulfilled Promise array literals',
90
+ expectedObserved: 20,
91
+ reducer: 'last',
92
+ source: [
93
+ 'export function main(callback: (value: number) => number): number {',
94
+ ' Promise.race([Promise.resolve(20), Promise.resolve(2)])',
95
+ ' .then((value) => {',
96
+ ' callback(value);',
97
+ ' return value + 1;',
98
+ ' });',
99
+ ' return 0;',
100
+ '}',
101
+ '',
102
+ ].join('\n'),
103
+ },
104
+ {
105
+ name: 'compileProject propagates Promise.race rejections from direct Promise array literals',
106
+ expectedObserved: 23,
107
+ reducer: 'last',
108
+ source: [
109
+ 'export function main(callback: (value: number) => number): number {',
110
+ ' Promise.race([Promise.reject<number>(20), Promise.resolve(2)])',
111
+ ' .catch(() => {',
112
+ ' callback(23);',
113
+ ' return 0;',
114
+ ' });',
115
+ ' return 0;',
116
+ '}',
117
+ '',
118
+ ].join('\n'),
119
+ },
120
+ {
121
+ name:
122
+ 'compileProject executes Promise.resolve then callbacks before exported functions return',
123
+ expectedObserved: 21,
124
+ reducer: 'last',
125
+ source: [
126
+ 'export function main(callback: (value: number) => number): number {',
127
+ ' Promise.resolve(20).then((value) => {',
128
+ ' callback(value + 1);',
129
+ ' return value + 2;',
130
+ ' });',
131
+ ' return 0;',
132
+ '}',
133
+ '',
134
+ ].join('\n'),
135
+ },
136
+ {
137
+ name: 'compileProject drains chained Promise.then callbacks before exported functions return',
138
+ expectedObserved: 25,
139
+ reducer: 'last',
140
+ source: [
141
+ 'export function main(callback: (value: number) => number): number {',
142
+ ' Promise.resolve(20)',
143
+ ' .then((value) => value + 2)',
144
+ ' .then((value) => {',
145
+ ' callback(value + 3);',
146
+ ' return value + 4;',
147
+ ' });',
148
+ ' return 0;',
149
+ '}',
150
+ '',
151
+ ].join('\n'),
152
+ },
153
+ {
154
+ name:
155
+ 'compileProject executes Promise.reject catch callbacks before exported functions return',
156
+ expectedObserved: 23,
157
+ reducer: 'last',
158
+ source: [
159
+ 'export function main(callback: (value: number) => number): number {',
160
+ ' Promise.reject(20)',
161
+ ' .catch(() => 22)',
162
+ ' .then((value) => {',
163
+ ' callback(value + 1);',
164
+ ' return value + 2;',
165
+ ' });',
166
+ ' return 0;',
167
+ '}',
168
+ '',
169
+ ].join('\n'),
170
+ },
171
+ {
172
+ name: 'compileProject propagates rejected Promises through then without handlers',
173
+ expectedObserved: 23,
174
+ reducer: 'last',
175
+ source: [
176
+ 'export function main(callback: (value: number) => number): number {',
177
+ ' Promise.reject(20)',
178
+ ' .then()',
179
+ ' .catch(() => 22)',
180
+ ' .then((value) => {',
181
+ ' callback(value + 1);',
182
+ ' return value + 2;',
183
+ ' });',
184
+ ' return 0;',
185
+ '}',
186
+ '',
187
+ ].join('\n'),
188
+ },
189
+ {
190
+ name: 'compileProject adopts Promise values returned from then callbacks',
191
+ expectedObserved: 25,
192
+ reducer: 'last',
193
+ source: [
194
+ 'export function main(callback: (value: number) => number): number {',
195
+ ' Promise.resolve(20)',
196
+ ' .then((value) => Promise.resolve(value + 2))',
197
+ ' .then((value) => {',
198
+ ' callback(value + 3);',
199
+ ' return value + 4;',
200
+ ' });',
201
+ ' return 0;',
202
+ '}',
203
+ '',
204
+ ].join('\n'),
205
+ },
206
+ {
207
+ name: 'compileProject adopts rejected Promise values returned from then callbacks',
208
+ expectedObserved: 25,
209
+ reducer: 'last',
210
+ source: [
211
+ 'export function main(callback: (value: number) => number): number {',
212
+ ' Promise.resolve(20)',
213
+ ' .then((value) => Promise.reject<number>(value + 2))',
214
+ ' .catch(() => {',
215
+ ' callback(25);',
216
+ ' return 26;',
217
+ ' });',
218
+ ' return 0;',
219
+ '}',
220
+ '',
221
+ ].join('\n'),
222
+ },
223
+ {
224
+ name:
225
+ 'compileProject treats Promise.resolve(existingPromise) as passthrough for fulfilled Promises',
226
+ expectedObserved: 21,
227
+ reducer: 'last',
228
+ source: [
229
+ 'export function main(callback: (value: number) => number): number {',
230
+ ' const promise = Promise.resolve(20);',
231
+ ' Promise.resolve(promise)',
232
+ ' .then((value) => {',
233
+ ' callback(value + 1);',
234
+ ' return value + 2;',
235
+ ' });',
236
+ ' return 0;',
237
+ '}',
238
+ '',
239
+ ].join('\n'),
240
+ },
241
+ {
242
+ name:
243
+ 'compileProject treats Promise.resolve(existingPromise) as passthrough for rejected Promises',
244
+ expectedObserved: 22,
245
+ reducer: 'last',
246
+ source: [
247
+ 'export function main(callback: (value: number) => number): number {',
248
+ ' const promise = Promise.reject(20);',
249
+ ' Promise.resolve(promise)',
250
+ ' .catch(() => {',
251
+ ' callback(22);',
252
+ ' return 23;',
253
+ ' });',
254
+ ' return 0;',
255
+ '}',
256
+ '',
257
+ ].join('\n'),
258
+ },
259
+ {
260
+ name: 'compileProject lowers local async functions that await fulfilled compiler-owned Promises',
261
+ expectedObserved: 23,
262
+ reducer: 'last',
263
+ source: [
264
+ 'export function main(callback: (value: number) => number): number {',
265
+ ' async function compute(): Promise<number> {',
266
+ ' const value = await Promise.resolve(20);',
267
+ ' return value + 2;',
268
+ ' }',
269
+ ' compute().then((value) => {',
270
+ ' callback(value + 1);',
271
+ ' return value;',
272
+ ' });',
273
+ ' return 0;',
274
+ '}',
275
+ '',
276
+ ].join('\n'),
277
+ },
278
+ {
279
+ name: 'compileProject lowers local async functions with sequential await steps',
280
+ expectedObserved: 23,
281
+ reducer: 'last',
282
+ source: [
283
+ 'export function main(callback: (value: number) => number): number {',
284
+ ' async function compute(): Promise<number> {',
285
+ ' const left = await Promise.resolve(20);',
286
+ ' const right = await Promise.resolve(2);',
287
+ ' return left + right;',
288
+ ' }',
289
+ ' compute().then((value) => {',
290
+ ' callback(value + 1);',
291
+ ' return value;',
292
+ ' });',
293
+ ' return 0;',
294
+ '}',
295
+ '',
296
+ ].join('\n'),
297
+ },
298
+ {
299
+ name: 'compileProject lowers straight-line async awaited reassignment through persisted frame locals',
300
+ expectedObserved: 23,
301
+ reducer: 'last',
302
+ source: [
303
+ 'export function main(callback: (value: number) => number): number {',
304
+ ' async function compute(): Promise<number> {',
305
+ ' let total = await Promise.resolve(20);',
306
+ ' total = await Promise.resolve(total + 2);',
307
+ ' return total;',
308
+ ' }',
309
+ ' compute().then((value) => {',
310
+ ' callback(value + 1);',
311
+ ' return value;',
312
+ ' });',
313
+ ' return 0;',
314
+ '}',
315
+ '',
316
+ ].join('\n'),
317
+ },
318
+ {
319
+ name: 'compileProject hoists local function declarations inside local async functions across await boundaries',
320
+ expectedObserved: 23,
321
+ reducer: 'last',
322
+ source: [
323
+ 'export function main(callback: (value: number) => number): number {',
324
+ ' async function compute(): Promise<number> {',
325
+ ' function addTwo(value: number): number {',
326
+ ' return value + 2;',
327
+ ' }',
328
+ ' const value = await Promise.resolve(20);',
329
+ ' return addTwo(value);',
330
+ ' }',
331
+ ' compute().then((value) => {',
332
+ ' callback(value + 1);',
333
+ ' return value;',
334
+ ' });',
335
+ ' return 0;',
336
+ '}',
337
+ '',
338
+ ].join('\n'),
339
+ },
340
+ {
341
+ name: 'compileProject propagates rejected await values through local async functions',
342
+ expectedObserved: 23,
343
+ reducer: 'last',
344
+ source: [
345
+ 'export function main(callback: (value: number) => number): number {',
346
+ ' async function compute(): Promise<number> {',
347
+ ' const value = await Promise.reject<number>(20);',
348
+ ' return value + 2;',
349
+ ' }',
350
+ ' compute().catch(() => {',
351
+ ' callback(23);',
352
+ ' return 0;',
353
+ ' });',
354
+ ' return 0;',
355
+ '}',
356
+ '',
357
+ ].join('\n'),
358
+ },
359
+ {
360
+ name: 'compileProject hoists local function declarations inside exported async functions across await boundaries',
361
+ source: [
362
+ 'export async function main(): Promise<number> {',
363
+ ' function addTwo(value: number): number {',
364
+ ' return value + 2;',
365
+ ' }',
366
+ ' const value = await Promise.resolve(20);',
367
+ ' return addTwo(value);',
368
+ '}',
369
+ '',
370
+ ].join('\n'),
371
+ async run(exported): Promise<void> {
372
+ const result = exported();
373
+ if (!(result instanceof Promise)) {
374
+ throw new Error('Expected exported async function to return a host Promise.');
375
+ }
376
+ assertEquals(await result, 22);
377
+ },
378
+ },
379
+ {
380
+ name: 'compileProject lowers local async arrow functions that await compiler-owned Promises',
381
+ expectedObserved: 23,
382
+ reducer: 'last',
383
+ source: [
384
+ 'export function main(callback: (value: number) => number): number {',
385
+ ' const compute = async (): Promise<number> => {',
386
+ ' const value = await Promise.resolve(20);',
387
+ ' return value + 2;',
388
+ ' };',
389
+ ' compute().then((value) => {',
390
+ ' callback(value + 1);',
391
+ ' return value;',
392
+ ' });',
393
+ ' return 0;',
394
+ '}',
395
+ '',
396
+ ].join('\n'),
397
+ },
398
+ {
399
+ name: 'compileProject lowers module-scope async helpers used from exported sync functions',
400
+ expectedObserved: 23,
401
+ reducer: 'last',
402
+ source: [
403
+ 'async function compute(): Promise<number> {',
404
+ ' const value = await Promise.resolve(20);',
405
+ ' return value + 2;',
406
+ '}',
407
+ '',
408
+ 'export function main(callback: (value: number) => number): number {',
409
+ ' compute().then((value) => {',
410
+ ' callback(value + 1);',
411
+ ' return value;',
412
+ ' });',
413
+ ' return 0;',
414
+ '}',
415
+ '',
416
+ ].join('\n'),
417
+ },
418
+ {
419
+ name: 'compileProject lowers await on plain fulfilled values inside local async functions',
420
+ expectedObserved: 23,
421
+ reducer: 'last',
422
+ source: [
423
+ 'export function main(callback: (value: number) => number): number {',
424
+ ' async function compute(): Promise<number> {',
425
+ ' const value = await 20;',
426
+ ' return value + 2;',
427
+ ' }',
428
+ ' compute().then((value) => {',
429
+ ' callback(value + 1);',
430
+ ' return value;',
431
+ ' });',
432
+ ' return 0;',
433
+ '}',
434
+ '',
435
+ ].join('\n'),
436
+ },
437
+ {
438
+ name: 'compileProject lowers async helpers without await by wrapping their return values',
439
+ expectedObserved: 23,
440
+ reducer: 'last',
441
+ source: [
442
+ 'async function compute(): Promise<number> {',
443
+ ' return 22;',
444
+ '}',
445
+ '',
446
+ 'export function main(callback: (value: number) => number): number {',
447
+ ' compute().then((value) => {',
448
+ ' callback(value + 1);',
449
+ ' return value;',
450
+ ' });',
451
+ ' return 0;',
452
+ '}',
453
+ '',
454
+ ].join('\n'),
455
+ },
456
+ {
457
+ name: 'compileProject lowers final async try/catch around rejected awaits',
458
+ expectedObserved: 23,
459
+ reducer: 'last',
460
+ source: [
461
+ 'export function main(callback: (value: number) => number): number {',
462
+ ' async function compute(): Promise<number> {',
463
+ ' try {',
464
+ ' const value = await Promise.reject<number>(20);',
465
+ ' return value + 2;',
466
+ ' } catch {',
467
+ ' return 22;',
468
+ ' }',
469
+ ' }',
470
+ ' compute().then((value) => {',
471
+ ' callback(value + 1);',
472
+ ' return value;',
473
+ ' });',
474
+ ' return 0;',
475
+ '}',
476
+ '',
477
+ ].join('\n'),
478
+ },
479
+ {
480
+ name: 'compileProject lowers final async try/catch with catch bindings',
481
+ expectedObserved: 23,
482
+ reducer: 'last',
483
+ source: [
484
+ 'export function main(callback: (value: number) => number): number {',
485
+ ' async function compute(): Promise<number> {',
486
+ ' try {',
487
+ ' const value = await Promise.reject<string>("boom");',
488
+ ' return value.length;',
489
+ ' } catch (error: unknown) {',
490
+ ' return 22;',
491
+ ' }',
492
+ ' }',
493
+ ' compute().then((value) => {',
494
+ ' callback(value + 1);',
495
+ ' return value;',
496
+ ' });',
497
+ ' return 0;',
498
+ '}',
499
+ '',
500
+ ].join('\n'),
501
+ },
502
+ {
503
+ name: 'compileProject lowers final async try/finally around fulfilled awaits',
504
+ expectedObserved: 22,
505
+ reducer: 'last',
506
+ source: [
507
+ 'export function main(callback: (value: number) => number): number {',
508
+ ' async function compute(): Promise<number> {',
509
+ ' try {',
510
+ ' return await Promise.resolve(20);',
511
+ ' } finally {',
512
+ ' callback(2);',
513
+ ' }',
514
+ ' }',
515
+ ' compute().then((value) => {',
516
+ ' callback(value + 2);',
517
+ ' return value;',
518
+ ' });',
519
+ ' return 0;',
520
+ '}',
521
+ '',
522
+ ].join('\n'),
523
+ },
524
+ {
525
+ name: 'compileProject lowers final async try/finally around rejected awaits',
526
+ expectedObserved: 22,
527
+ reducer: 'last',
528
+ source: [
529
+ 'export function main(callback: (value: number) => number): number {',
530
+ ' async function compute(): Promise<number> {',
531
+ ' try {',
532
+ ' return await Promise.reject<number>(20);',
533
+ ' } finally {',
534
+ ' callback(2);',
535
+ ' }',
536
+ ' }',
537
+ ' compute().catch(() => {',
538
+ ' callback(22);',
539
+ ' return 0;',
540
+ ' });',
541
+ ' return 0;',
542
+ '}',
543
+ '',
544
+ ].join('\n'),
545
+ },
546
+ {
547
+ name: 'compileProject lowers final async try/finally with return inside finally',
548
+ expectedObserved: 23,
549
+ reducer: 'last',
550
+ source: [
551
+ 'export function main(callback: (value: number) => number): number {',
552
+ ' async function compute(): Promise<number> {',
553
+ ' try {',
554
+ ' return await Promise.resolve(20);',
555
+ ' } finally {',
556
+ ' return 22;',
557
+ ' }',
558
+ ' }',
559
+ ' compute().then((value) => {',
560
+ ' callback(value + 1);',
561
+ ' return value;',
562
+ ' });',
563
+ ' return 0;',
564
+ '}',
565
+ '',
566
+ ].join('\n'),
567
+ },
568
+ {
569
+ name: 'compileProject lowers final async try/finally with return inside finally after rejection',
570
+ expectedObserved: 23,
571
+ reducer: 'last',
572
+ source: [
573
+ 'export function main(callback: (value: number) => number): number {',
574
+ ' async function compute(): Promise<number> {',
575
+ ' try {',
576
+ ' return await Promise.reject<number>(20);',
577
+ ' } finally {',
578
+ ' return 22;',
579
+ ' }',
580
+ ' }',
581
+ ' compute().then((value) => {',
582
+ ' callback(value + 1);',
583
+ ' return value;',
584
+ ' });',
585
+ ' return 0;',
586
+ '}',
587
+ '',
588
+ ].join('\n'),
589
+ },
590
+ {
591
+ name: 'compileProject preserves non-final async try/finally returns from try bodies',
592
+ expectedObserved: 23,
593
+ reducer: 'last',
594
+ source: [
595
+ 'export function main(callback: (value: number) => number): number {',
596
+ ' async function compute(): Promise<number> {',
597
+ ' try {',
598
+ ' return await Promise.resolve(22);',
599
+ ' } finally {',
600
+ ' callback(2);',
601
+ ' }',
602
+ ' callback(100);',
603
+ ' return 0;',
604
+ ' }',
605
+ ' compute().then((value) => {',
606
+ ' callback(value + 1);',
607
+ ' return value;',
608
+ ' });',
609
+ ' return 0;',
610
+ '}',
611
+ '',
612
+ ].join('\n'),
613
+ },
614
+ {
615
+ name: 'compileProject preserves non-final async try/finally returns from finally bodies',
616
+ expectedObserved: 23,
617
+ reducer: 'last',
618
+ source: [
619
+ 'export function main(callback: (value: number) => number): number {',
620
+ ' async function compute(): Promise<number> {',
621
+ ' try {',
622
+ ' await Promise.resolve(20);',
623
+ ' } finally {',
624
+ ' return 22;',
625
+ ' }',
626
+ ' callback(100);',
627
+ ' return 0;',
628
+ ' }',
629
+ ' compute().then((value) => {',
630
+ ' callback(value + 1);',
631
+ ' return value;',
632
+ ' });',
633
+ ' return 0;',
634
+ '}',
635
+ '',
636
+ ].join('\n'),
637
+ },
638
+ {
639
+ name: 'compileProject lowers non-final async try/catch and continues afterward',
640
+ expectedObserved: 23,
641
+ reducer: 'last',
642
+ source: [
643
+ 'export function main(callback: (value: number) => number): number {',
644
+ ' async function compute(): Promise<number> {',
645
+ ' let total = 0;',
646
+ ' try {',
647
+ ' total = await Promise.reject<number>(20);',
648
+ ' } catch {',
649
+ ' total = 20;',
650
+ ' }',
651
+ ' return total + 2;',
652
+ ' }',
653
+ ' compute().then((value) => {',
654
+ ' callback(value + 1);',
655
+ ' return value;',
656
+ ' });',
657
+ ' return 0;',
658
+ '}',
659
+ '',
660
+ ].join('\n'),
661
+ },
662
+ {
663
+ name: 'compileProject lowers non-final async try/catch/finally and continues afterward',
664
+ expectedObserved: 22,
665
+ reducer: 'last',
666
+ source: [
667
+ 'export function main(callback: (value: number) => number): number {',
668
+ ' async function compute(): Promise<number> {',
669
+ ' let total = 0;',
670
+ ' try {',
671
+ ' total = await Promise.reject<number>(20);',
672
+ ' } catch {',
673
+ ' total = 20;',
674
+ ' } finally {',
675
+ ' total = total + 1;',
676
+ ' }',
677
+ ' return total + 1;',
678
+ ' }',
679
+ ' compute().then((value) => {',
680
+ ' callback(value);',
681
+ ' return value;',
682
+ ' });',
683
+ ' return 0;',
684
+ '}',
685
+ '',
686
+ ].join('\n'),
687
+ },
688
+ {
689
+ name: 'compileProject preserves non-final async try/catch returns from catch bodies',
690
+ expectedObserved: 23,
691
+ reducer: 'last',
692
+ source: [
693
+ 'export function main(callback: (value: number) => number): number {',
694
+ ' async function compute(): Promise<number> {',
695
+ ' try {',
696
+ ' await Promise.reject<number>(20);',
697
+ ' } catch {',
698
+ ' return 22;',
699
+ ' }',
700
+ ' callback(100);',
701
+ ' return 0;',
702
+ ' }',
703
+ ' compute().then((value) => {',
704
+ ' callback(value + 1);',
705
+ ' return value;',
706
+ ' });',
707
+ ' return 0;',
708
+ '}',
709
+ '',
710
+ ].join('\n'),
711
+ },
712
+ {
713
+ name: 'compileProject lowers top-level async if branches with awaited values',
714
+ expectedObserved: 23,
715
+ reducer: 'last',
716
+ source: [
717
+ 'export function main(callback: (value: number) => number, flag: boolean): number {',
718
+ ' async function compute(): Promise<number> {',
719
+ ' if (flag) {',
720
+ ' const left = await Promise.resolve(20);',
721
+ ' return left + 2;',
722
+ ' }',
723
+ ' const right = await Promise.resolve(2);',
724
+ ' return right + 20;',
725
+ ' }',
726
+ ' compute().then((value) => {',
727
+ ' callback(value + 1);',
728
+ ' return value;',
729
+ ' });',
730
+ ' return 0;',
731
+ '}',
732
+ '',
733
+ ].join('\n'),
734
+ run: async (exported) => {
735
+ let observed = 0;
736
+ assertEquals(
737
+ exported((value: number) => {
738
+ observed = value;
739
+ return value;
740
+ }, true),
741
+ 0,
742
+ );
743
+ assertEquals(observed, 23);
744
+ observed = 0;
745
+ assertEquals(
746
+ exported((value: number) => {
747
+ observed = value;
748
+ return value;
749
+ }, false),
750
+ 0,
751
+ );
752
+ assertEquals(observed, 23);
753
+ },
754
+ },
755
+ {
756
+ name: 'compileProject lowers top-level async if and continues after the branch',
757
+ expectedObserved: 24,
758
+ reducer: 'last',
759
+ source: [
760
+ 'export function main(callback: (value: number) => number, flag: boolean): number {',
761
+ ' async function compute(): Promise<number> {',
762
+ ' if (flag) {',
763
+ ' await Promise.resolve(20);',
764
+ ' } else {',
765
+ ' await Promise.resolve(2);',
766
+ ' }',
767
+ ' return 23;',
768
+ ' }',
769
+ ' compute().then((value) => {',
770
+ ' callback(value + 1);',
771
+ ' return value;',
772
+ ' });',
773
+ ' return 0;',
774
+ '}',
775
+ '',
776
+ ].join('\n'),
777
+ run: async (exported) => {
778
+ let observed = 0;
779
+ assertEquals(
780
+ exported((value: number) => {
781
+ observed = value;
782
+ return value;
783
+ }, true),
784
+ 0,
785
+ );
786
+ assertEquals(observed, 24);
787
+ observed = 0;
788
+ assertEquals(
789
+ exported((value: number) => {
790
+ observed = value;
791
+ return value;
792
+ }, false),
793
+ 0,
794
+ );
795
+ assertEquals(observed, 24);
796
+ },
797
+ },
798
+ {
799
+ name: 'compileProject lowers top-level async if with sync fallthrough branch',
800
+ expectedObserved: 24,
801
+ reducer: 'last',
802
+ source: [
803
+ 'export function main(callback: (value: number) => number, flag: boolean): number {',
804
+ ' async function compute(): Promise<number> {',
805
+ ' if (flag) {',
806
+ ' await Promise.resolve(20);',
807
+ ' }',
808
+ ' return 23;',
809
+ ' }',
810
+ ' compute().then((value) => {',
811
+ ' callback(value + 1);',
812
+ ' return value;',
813
+ ' });',
814
+ ' return 0;',
815
+ '}',
816
+ '',
817
+ ].join('\n'),
818
+ run: async (exported) => {
819
+ let observed = 0;
820
+ assertEquals(
821
+ exported((value: number) => {
822
+ observed = value;
823
+ return value;
824
+ }, true),
825
+ 0,
826
+ );
827
+ assertEquals(observed, 24);
828
+ observed = 0;
829
+ assertEquals(
830
+ exported((value: number) => {
831
+ observed = value;
832
+ return value;
833
+ }, false),
834
+ 0,
835
+ );
836
+ assertEquals(observed, 24);
837
+ },
838
+ },
839
+ {
840
+ name: 'compileProject preserves mutable locals across async if branches',
841
+ expectedObserved: 23,
842
+ reducer: 'last',
843
+ source: [
844
+ 'export function main(callback: (value: number) => number, flag: boolean): number {',
845
+ ' async function compute(): Promise<number> {',
846
+ ' let total = 0;',
847
+ ' if (flag) {',
848
+ ' total = await Promise.resolve(20);',
849
+ ' } else {',
850
+ ' total = await Promise.resolve(21);',
851
+ ' }',
852
+ ' return flag ? total + 2 : total + 1;',
853
+ ' }',
854
+ ' compute().then((value) => {',
855
+ ' callback(value);',
856
+ ' return value;',
857
+ ' });',
858
+ ' return 0;',
859
+ '}',
860
+ '',
861
+ ].join('\n'),
862
+ run: async (exported) => {
863
+ let observed = 0;
864
+ assertEquals(
865
+ exported((value: number) => {
866
+ observed = value;
867
+ return value;
868
+ }, true),
869
+ 0,
870
+ );
871
+ assertEquals(observed, 22);
872
+ observed = 0;
873
+ assertEquals(
874
+ exported((value: number) => {
875
+ observed = value;
876
+ return value;
877
+ }, false),
878
+ 0,
879
+ );
880
+ assertEquals(observed, 22);
881
+ },
882
+ },
883
+ {
884
+ name: 'compileProject preserves mutable locals across async while loops',
885
+ expectedObserved: 6,
886
+ reducer: 'last',
887
+ source: [
888
+ 'export function main(callback: (value: number) => number): number {',
889
+ ' async function compute(): Promise<number> {',
890
+ ' let current = 0;',
891
+ ' let total = 0;',
892
+ ' while (current < 3) {',
893
+ ' const next = await Promise.resolve(current + 1);',
894
+ ' total = total + next;',
895
+ ' current = current + 1;',
896
+ ' }',
897
+ ' return total;',
898
+ ' }',
899
+ ' compute().then((value) => {',
900
+ ' callback(value);',
901
+ ' return value;',
902
+ ' });',
903
+ ' return 0;',
904
+ '}',
905
+ '',
906
+ ].join('\n'),
907
+ },
908
+ {
909
+ name: 'compileProject supports top-level async while break statements',
910
+ expectedObserved: 11,
911
+ reducer: 'last',
912
+ source: [
913
+ 'export function main(callback: (value: number) => number): number {',
914
+ ' async function compute(): Promise<number> {',
915
+ ' let current = 0;',
916
+ ' let total = 0;',
917
+ ' while (current < 5) {',
918
+ ' current = current + 1;',
919
+ ' const next = await Promise.resolve(current);',
920
+ ' total = total + next;',
921
+ ' break;',
922
+ ' }',
923
+ ' return current * 10 + total;',
924
+ ' }',
925
+ ' compute().then((value) => {',
926
+ ' callback(value);',
927
+ ' return value;',
928
+ ' });',
929
+ ' return 0;',
930
+ '}',
931
+ '',
932
+ ].join('\n'),
933
+ },
934
+ {
935
+ name: 'compileProject supports top-level async while continue statements',
936
+ expectedObserved: 3,
937
+ reducer: 'last',
938
+ source: [
939
+ 'export function main(callback: (value: number) => number): number {',
940
+ ' async function compute(): Promise<number> {',
941
+ ' let current = 0;',
942
+ ' let total = 0;',
943
+ ' while (current < 3) {',
944
+ ' current = current + 1;',
945
+ ' await Promise.resolve(current);',
946
+ ' continue;',
947
+ ' total = total + 100;',
948
+ ' }',
949
+ ' return current + total;',
950
+ ' }',
951
+ ' compute().then((value) => {',
952
+ ' callback(value);',
953
+ ' return value;',
954
+ ' });',
955
+ ' return 0;',
956
+ '}',
957
+ '',
958
+ ].join('\n'),
959
+ },
960
+ {
961
+ name: 'compileProject supports conditional async while break and continue statements',
962
+ expectedObserved: 8,
963
+ reducer: 'last',
964
+ source: [
965
+ 'export function main(callback: (value: number) => number): number {',
966
+ ' async function compute(): Promise<number> {',
967
+ ' let current = 0;',
968
+ ' let total = 0;',
969
+ ' while (current < 5) {',
970
+ ' current = current + 1;',
971
+ ' if (current === 2) {',
972
+ ' continue;',
973
+ ' }',
974
+ ' const next = await Promise.resolve(current);',
975
+ ' total = total + next;',
976
+ ' if (current === 4) {',
977
+ ' break;',
978
+ ' }',
979
+ ' }',
980
+ ' return total;',
981
+ ' }',
982
+ ' compute().then((value) => {',
983
+ ' callback(value);',
984
+ ' return value;',
985
+ ' });',
986
+ ' return 0;',
987
+ '}',
988
+ '',
989
+ ].join('\n'),
990
+ },
991
+ {
992
+ name: 'compileProject supports return statements inside async while loops',
993
+ expectedObserved: 21,
994
+ reducer: 'last',
995
+ source: [
996
+ 'export function main(callback: (value: number) => number): number {',
997
+ ' async function compute(): Promise<number> {',
998
+ ' let current = 0;',
999
+ ' while (current < 5) {',
1000
+ ' current = current + 1;',
1001
+ ' const next = await Promise.resolve(current);',
1002
+ ' return next + 20;',
1003
+ ' }',
1004
+ ' return 0;',
1005
+ ' }',
1006
+ ' compute().then((value) => {',
1007
+ ' callback(value);',
1008
+ ' return value;',
1009
+ ' });',
1010
+ ' return 0;',
1011
+ '}',
1012
+ '',
1013
+ ].join('\n'),
1014
+ },
1015
+ {
1016
+ name: 'compileProject bridges exported async functions to host Promises',
1017
+ source: [
1018
+ 'export async function main(): Promise<number> {',
1019
+ ' const value = await Promise.resolve(20);',
1020
+ ' return value + 2;',
1021
+ '}',
1022
+ '',
1023
+ ].join('\n'),
1024
+ run: async (exported) => {
1025
+ const result = exported();
1026
+ if (!(result instanceof Promise)) {
1027
+ throw new Error('Expected exported async function to return a host Promise.');
1028
+ }
1029
+ assertEquals(await result, 22);
1030
+ },
1031
+ },
1032
+ {
1033
+ name: 'compileProject bridges exported async while loops with awaited mutable locals',
1034
+ source: [
1035
+ 'export async function main(): Promise<number> {',
1036
+ ' let current = 0;',
1037
+ ' let total = 0;',
1038
+ ' while (current < 3) {',
1039
+ ' const next = await Promise.resolve(current + 1);',
1040
+ ' total = total + next;',
1041
+ ' current = current + 1;',
1042
+ ' }',
1043
+ ' return total;',
1044
+ '}',
1045
+ '',
1046
+ ].join('\n'),
1047
+ run: async (exported) => {
1048
+ const result = exported();
1049
+ if (!(result instanceof Promise)) {
1050
+ throw new Error('Expected exported async while loop to return a host Promise.');
1051
+ }
1052
+ assertEquals(await result, 6);
1053
+ },
1054
+ },
1055
+ {
1056
+ name: 'compileProject bridges exported async for loops with top-level continue statements',
1057
+ source: [
1058
+ 'export async function main(): Promise<number> {',
1059
+ ' let current = 0;',
1060
+ ' let total = 0;',
1061
+ ' for (; current < 3; current = current + 1) {',
1062
+ ' await Promise.resolve(current + 1);',
1063
+ ' continue;',
1064
+ ' total = total + 100;',
1065
+ ' }',
1066
+ ' return current + total;',
1067
+ '}',
1068
+ '',
1069
+ ].join('\n'),
1070
+ run: async (exported) => {
1071
+ const result = exported();
1072
+ if (!(result instanceof Promise)) {
1073
+ throw new Error('Expected exported async for loop with continue to return a host Promise.');
1074
+ }
1075
+ assertEquals(await result, 3);
1076
+ },
1077
+ },
1078
+ {
1079
+ name: 'compileProject bridges exported async for let loops with continue statements',
1080
+ source: [
1081
+ 'export async function main(): Promise<number> {',
1082
+ ' let total = 0;',
1083
+ ' for (let current = 0; current < 3; current = current + 1) {',
1084
+ ' if (current === 1) {',
1085
+ ' continue;',
1086
+ ' }',
1087
+ ' const next = await Promise.resolve(current + 1);',
1088
+ ' total = total + next;',
1089
+ ' }',
1090
+ ' return total;',
1091
+ '}',
1092
+ '',
1093
+ ].join('\n'),
1094
+ run: async (exported) => {
1095
+ const result = exported();
1096
+ if (!(result instanceof Promise)) {
1097
+ throw new Error('Expected exported async for let loop to return a host Promise.');
1098
+ }
1099
+ assertEquals(await result, 4);
1100
+ },
1101
+ },
1102
+ {
1103
+ name: 'compileProject preserves mutable locals across async for loops',
1104
+ expectedObserved: 6,
1105
+ reducer: 'last',
1106
+ source: [
1107
+ 'export function main(callback: (value: number) => number): number {',
1108
+ ' async function compute(): Promise<number> {',
1109
+ ' let current = 0;',
1110
+ ' let total = 0;',
1111
+ ' for (; current < 3; current = current + 1) {',
1112
+ ' const next = await Promise.resolve(current + 1);',
1113
+ ' total = total + next;',
1114
+ ' }',
1115
+ ' return total;',
1116
+ ' }',
1117
+ ' compute().then((value) => {',
1118
+ ' callback(value);',
1119
+ ' return value;',
1120
+ ' });',
1121
+ ' return 0;',
1122
+ '}',
1123
+ '',
1124
+ ].join('\n'),
1125
+ },
1126
+ {
1127
+ name: 'compileProject lowers async for loops with expression initializers',
1128
+ expectedObserved: 6,
1129
+ reducer: 'last',
1130
+ source: [
1131
+ 'export function main(callback: (value: number) => number): number {',
1132
+ ' async function compute(): Promise<number> {',
1133
+ ' let current = 0;',
1134
+ ' let total = 0;',
1135
+ ' for (current = 0; current < 3; current = current + 1) {',
1136
+ ' const next = await Promise.resolve(current + 1);',
1137
+ ' total = total + next;',
1138
+ ' }',
1139
+ ' return total;',
1140
+ ' }',
1141
+ ' compute().then((value) => {',
1142
+ ' callback(value);',
1143
+ ' return value;',
1144
+ ' });',
1145
+ ' return 0;',
1146
+ '}',
1147
+ '',
1148
+ ].join('\n'),
1149
+ },
1150
+ {
1151
+ name: 'compileProject keeps async for let loop bindings out of later async continuations',
1152
+ expectedObserved: 27,
1153
+ reducer: 'last',
1154
+ source: [
1155
+ 'export function main(callback: (value: number) => number): number {',
1156
+ ' async function compute(): Promise<number> {',
1157
+ ' let current = 20;',
1158
+ ' let total = 0;',
1159
+ ' for (let current = 0; current < 3; current = current + 1) {',
1160
+ ' const next = await Promise.resolve(current + 1);',
1161
+ ' total = total + next;',
1162
+ ' }',
1163
+ ' return current + total;',
1164
+ ' }',
1165
+ ' compute().then((value) => {',
1166
+ ' callback(value + 1);',
1167
+ ' return value;',
1168
+ ' });',
1169
+ ' return 0;',
1170
+ '}',
1171
+ '',
1172
+ ].join('\n'),
1173
+ },
1174
+ {
1175
+ name: 'compileProject supports top-level async for break statements',
1176
+ expectedObserved: 1,
1177
+ reducer: 'last',
1178
+ source: [
1179
+ 'export function main(callback: (value: number) => number): number {',
1180
+ ' async function compute(): Promise<number> {',
1181
+ ' let current = 0;',
1182
+ ' let total = 0;',
1183
+ ' for (; current < 5; current = current + 1) {',
1184
+ ' const next = await Promise.resolve(current + 1);',
1185
+ ' total = total + next;',
1186
+ ' break;',
1187
+ ' }',
1188
+ ' return current * 10 + total;',
1189
+ ' }',
1190
+ ' compute().then((value) => {',
1191
+ ' callback(value);',
1192
+ ' return value;',
1193
+ ' });',
1194
+ ' return 0;',
1195
+ '}',
1196
+ '',
1197
+ ].join('\n'),
1198
+ },
1199
+ {
1200
+ name: 'compileProject supports top-level async for continue statements',
1201
+ expectedObserved: 3,
1202
+ reducer: 'last',
1203
+ source: [
1204
+ 'export function main(callback: (value: number) => number): number {',
1205
+ ' async function compute(): Promise<number> {',
1206
+ ' let current = 0;',
1207
+ ' let total = 0;',
1208
+ ' for (; current < 3; current = current + 1) {',
1209
+ ' await Promise.resolve(current + 1);',
1210
+ ' continue;',
1211
+ ' total = total + 100;',
1212
+ ' }',
1213
+ ' return current + total;',
1214
+ ' }',
1215
+ ' compute().then((value) => {',
1216
+ ' callback(value);',
1217
+ ' return value;',
1218
+ ' });',
1219
+ ' return 0;',
1220
+ '}',
1221
+ '',
1222
+ ].join('\n'),
1223
+ },
1224
+ {
1225
+ name: 'compileProject supports conditional async for break and continue statements',
1226
+ expectedObserved: 24,
1227
+ reducer: 'last',
1228
+ source: [
1229
+ 'export function main(callback: (value: number) => number): number {',
1230
+ ' async function compute(): Promise<number> {',
1231
+ ' let current = 0;',
1232
+ ' let total = 0;',
1233
+ ' for (; current < 5; current = current + 1) {',
1234
+ ' if (current === 1) {',
1235
+ ' continue;',
1236
+ ' }',
1237
+ ' const next = await Promise.resolve(current + 1);',
1238
+ ' total = total + next;',
1239
+ ' if (current === 2) {',
1240
+ ' break;',
1241
+ ' }',
1242
+ ' }',
1243
+ ' return current * 10 + total;',
1244
+ ' }',
1245
+ ' compute().then((value) => {',
1246
+ ' callback(value);',
1247
+ ' return value;',
1248
+ ' });',
1249
+ ' return 0;',
1250
+ '}',
1251
+ '',
1252
+ ].join('\n'),
1253
+ },
1254
+ {
1255
+ name: 'compileProject preserves continue completion through async for finally blocks',
1256
+ expectedObserved: 303,
1257
+ reducer: 'last',
1258
+ source: [
1259
+ 'export function main(callback: (value: number) => number): number {',
1260
+ ' async function compute(): Promise<number> {',
1261
+ ' let current = 0;',
1262
+ ' let total = 0;',
1263
+ ' for (; current < 3; current = current + 1) {',
1264
+ ' try {',
1265
+ ' total = total + 100;',
1266
+ ' } finally {',
1267
+ ' await Promise.resolve(current);',
1268
+ ' continue;',
1269
+ ' }',
1270
+ ' total = total + 1;',
1271
+ ' }',
1272
+ ' return total + current;',
1273
+ ' }',
1274
+ ' compute().then((value) => {',
1275
+ ' callback(value);',
1276
+ ' return value;',
1277
+ ' });',
1278
+ ' return 0;',
1279
+ '}',
1280
+ '',
1281
+ ].join('\n'),
1282
+ },
1283
+ {
1284
+ name: 'compileProject preserves break completion through async for finally blocks',
1285
+ expectedObserved: 100,
1286
+ reducer: 'last',
1287
+ source: [
1288
+ 'export function main(callback: (value: number) => number): number {',
1289
+ ' async function compute(): Promise<number> {',
1290
+ ' let current = 0;',
1291
+ ' let total = 0;',
1292
+ ' for (; current < 5; current = current + 1) {',
1293
+ ' try {',
1294
+ ' total = total + 100;',
1295
+ ' } finally {',
1296
+ ' await Promise.resolve(current);',
1297
+ ' break;',
1298
+ ' }',
1299
+ ' total = total + 1;',
1300
+ ' }',
1301
+ ' return total + current;',
1302
+ ' }',
1303
+ ' compute().then((value) => {',
1304
+ ' callback(value);',
1305
+ ' return value;',
1306
+ ' });',
1307
+ ' return 0;',
1308
+ '}',
1309
+ '',
1310
+ ].join('\n'),
1311
+ },
1312
+ {
1313
+ name: 'compileProject preserves catch bindings through async for try catch continue',
1314
+ expectedObserved: 23,
1315
+ reducer: 'last',
1316
+ source: [
1317
+ 'export function main(callback: (value: number) => number): number {',
1318
+ ' async function compute(): Promise<number> {',
1319
+ ' let total = 0;',
1320
+ ' for (; total < 2;) {',
1321
+ ' try {',
1322
+ ' await Promise.reject<string>("boom");',
1323
+ ' total = 100;',
1324
+ ' } catch (error: unknown) {',
1325
+ ' total = total + 1;',
1326
+ ' continue;',
1327
+ ' }',
1328
+ ' }',
1329
+ ' return total + 20;',
1330
+ ' }',
1331
+ ' compute().then((value) => {',
1332
+ ' callback(value + 1);',
1333
+ ' return value;',
1334
+ ' });',
1335
+ ' return 0;',
1336
+ '}',
1337
+ '',
1338
+ ].join('\n'),
1339
+ },
1340
+ {
1341
+ name: 'compileProject supports return statements inside async for loops',
1342
+ expectedObserved: 22,
1343
+ reducer: 'last',
1344
+ source: [
1345
+ 'export function main(callback: (value: number) => number): number {',
1346
+ ' async function compute(): Promise<number> {',
1347
+ ' let current = 0;',
1348
+ ' for (; current < 5; current = current + 1) {',
1349
+ ' const next = await Promise.resolve(current + 1);',
1350
+ ' return next + 21;',
1351
+ ' }',
1352
+ ' return 0;',
1353
+ ' }',
1354
+ ' compute().then((value) => {',
1355
+ ' callback(value);',
1356
+ ' return value;',
1357
+ ' });',
1358
+ ' return 0;',
1359
+ '}',
1360
+ '',
1361
+ ].join('\n'),
1362
+ },
1363
+ {
1364
+ name: 'compileProject supports return statements inside async for finally blocks',
1365
+ expectedObserved: 23,
1366
+ reducer: 'last',
1367
+ source: [
1368
+ 'export function main(callback: (value: number) => number): number {',
1369
+ ' async function compute(): Promise<number> {',
1370
+ ' let current = 0;',
1371
+ ' for (; current < 2; current = current + 1) {',
1372
+ ' try {',
1373
+ ' await Promise.resolve(current + 1);',
1374
+ ' } finally {',
1375
+ ' return 22;',
1376
+ ' }',
1377
+ ' }',
1378
+ ' return 0;',
1379
+ ' }',
1380
+ ' compute().then((value) => {',
1381
+ ' callback(value + 1);',
1382
+ ' return value;',
1383
+ ' });',
1384
+ ' return 0;',
1385
+ '}',
1386
+ '',
1387
+ ].join('\n'),
1388
+ },
1389
+ {
1390
+ name: 'compileProject preserves continue completion through async for try finally',
1391
+ expectedObserved: 22,
1392
+ reducer: 'last',
1393
+ source: [
1394
+ 'export function main(callback: (value: number) => number): number {',
1395
+ ' async function compute(): Promise<number> {',
1396
+ ' let current = 0;',
1397
+ ' let total = 0;',
1398
+ ' for (; current < 2; current = current + 1) {',
1399
+ ' try {',
1400
+ ' await Promise.resolve(current + 1);',
1401
+ ' continue;',
1402
+ ' } finally {',
1403
+ ' total = total + 1;',
1404
+ ' }',
1405
+ ' }',
1406
+ ' return current * 10 + total;',
1407
+ ' }',
1408
+ ' compute().then((value) => {',
1409
+ ' callback(value);',
1410
+ ' return value;',
1411
+ ' });',
1412
+ ' return 0;',
1413
+ '}',
1414
+ '',
1415
+ ].join('\n'),
1416
+ },
1417
+ {
1418
+ name: 'compileProject preserves return completion through exported async for try finally',
1419
+ source: [
1420
+ 'export async function main(): Promise<number> {',
1421
+ ' let total = 0;',
1422
+ ' for (; total < 1; total = total + 1) {',
1423
+ ' try {',
1424
+ ' const next = await Promise.resolve(20);',
1425
+ ' return next + 1;',
1426
+ ' } finally {',
1427
+ ' total = total + 1;',
1428
+ ' }',
1429
+ ' }',
1430
+ ' return 0;',
1431
+ '}',
1432
+ '',
1433
+ ].join('\n'),
1434
+ run: async (exported) => {
1435
+ const result = exported();
1436
+ if (!(result instanceof Promise)) {
1437
+ throw new Error('Expected exported async for loop with return to return a host Promise.');
1438
+ }
1439
+ assertEquals(await result, 21);
1440
+ },
1441
+ },
1442
+ {
1443
+ name: 'compileProject preserves break completion through async for try finally',
1444
+ expectedObserved: 11,
1445
+ reducer: 'last',
1446
+ source: [
1447
+ 'export function main(callback: (value: number) => number): number {',
1448
+ ' async function compute(): Promise<number> {',
1449
+ ' let current = 0;',
1450
+ ' let total = 0;',
1451
+ ' for (; current < 5; current = current + 1) {',
1452
+ ' try {',
1453
+ ' const next = await Promise.resolve(current + 1);',
1454
+ ' total = total + next;',
1455
+ ' break;',
1456
+ ' } finally {',
1457
+ ' total = total + 10;',
1458
+ ' }',
1459
+ ' }',
1460
+ ' return current * 100 + total;',
1461
+ ' }',
1462
+ ' compute().then((value) => {',
1463
+ ' callback(value);',
1464
+ ' return value;',
1465
+ ' });',
1466
+ ' return 0;',
1467
+ '}',
1468
+ '',
1469
+ ].join('\n'),
1470
+ },
1471
+ {
1472
+ name: 'compileProject preserves continue completion through async for try catch',
1473
+ expectedObserved: 3,
1474
+ reducer: 'last',
1475
+ source: [
1476
+ 'export function main(callback: (value: number) => number): number {',
1477
+ ' async function compute(): Promise<number> {',
1478
+ ' let current = 0;',
1479
+ ' let total = 0;',
1480
+ ' for (; current < 3; current = current + 1) {',
1481
+ ' try {',
1482
+ ' await Promise.reject<number>(current + 1);',
1483
+ ' } catch {',
1484
+ ' continue;',
1485
+ ' }',
1486
+ ' total = total + 100;',
1487
+ ' }',
1488
+ ' return current + total;',
1489
+ ' }',
1490
+ ' compute().then((value) => {',
1491
+ ' callback(value);',
1492
+ ' return value;',
1493
+ ' });',
1494
+ ' return 0;',
1495
+ '}',
1496
+ '',
1497
+ ].join('\n'),
1498
+ },
1499
+ {
1500
+ name: 'compileProject preserves break completion through async for try catch',
1501
+ expectedObserved: 7,
1502
+ reducer: 'last',
1503
+ source: [
1504
+ 'export function main(callback: (value: number) => number): number {',
1505
+ ' async function compute(): Promise<number> {',
1506
+ ' let current = 0;',
1507
+ ' let total = 0;',
1508
+ ' for (; current < 5; current = current + 1) {',
1509
+ ' try {',
1510
+ ' await Promise.reject<number>(current + 1);',
1511
+ ' } catch {',
1512
+ ' total = total + 7;',
1513
+ ' break;',
1514
+ ' }',
1515
+ ' total = total + 100;',
1516
+ ' }',
1517
+ ' return current * 10 + total;',
1518
+ ' }',
1519
+ ' compute().then((value) => {',
1520
+ ' callback(value);',
1521
+ ' return value;',
1522
+ ' });',
1523
+ ' return 0;',
1524
+ '}',
1525
+ '',
1526
+ ].join('\n'),
1527
+ },
1528
+ {
1529
+ name: 'compileProject bridges exported async for loops with awaited mutable locals',
1530
+ source: [
1531
+ 'export async function main(): Promise<number> {',
1532
+ ' let current = 0;',
1533
+ ' let total = 0;',
1534
+ ' for (; current < 3; current = current + 1) {',
1535
+ ' const next = await Promise.resolve(current + 1);',
1536
+ ' total = total + next;',
1537
+ ' }',
1538
+ ' return total;',
1539
+ '}',
1540
+ '',
1541
+ ].join('\n'),
1542
+ run: async (exported) => {
1543
+ const result = exported();
1544
+ if (!(result instanceof Promise)) {
1545
+ throw new Error('Expected exported async for loop to return a host Promise.');
1546
+ }
1547
+ assertEquals(await result, 6);
1548
+ },
1549
+ },
1550
+ {
1551
+ name: 'compileProject awaits ambient imported host Promise results',
1552
+ source: [
1553
+ 'declare function fetchNumber(): Promise<number>;',
1554
+ '',
1555
+ 'export async function main(): Promise<number> {',
1556
+ ' return await fetchNumber();',
1557
+ '}',
1558
+ '',
1559
+ ].join('\n'),
1560
+ hostFunctions: {
1561
+ 'src/index.ts:fetchNumber': () => Promise.resolve(22),
1562
+ },
1563
+ run: async (exported) => {
1564
+ const result = exported();
1565
+ if (!(result instanceof Promise)) {
1566
+ throw new Error('Expected exported async ambient import to return a host Promise.');
1567
+ }
1568
+ assertEquals(await result, 22);
1569
+ },
1570
+ },
1571
+ {
1572
+ name: 'compileProject catches rejected ambient imported host Promise results',
1573
+ source: [
1574
+ 'declare function fetchNumber(): Promise<number>;',
1575
+ '',
1576
+ 'export async function main(): Promise<number> {',
1577
+ ' try {',
1578
+ ' return await fetchNumber();',
1579
+ ' } catch {',
1580
+ ' return 22;',
1581
+ ' }',
1582
+ '}',
1583
+ '',
1584
+ ].join('\n'),
1585
+ hostFunctions: {
1586
+ 'src/index.ts:fetchNumber': () => Promise.reject(20),
1587
+ },
1588
+ run: async (exported) => {
1589
+ const result = exported();
1590
+ if (!(result instanceof Promise)) {
1591
+ throw new Error('Expected exported async ambient import catch to return a host Promise.');
1592
+ }
1593
+ assertEquals(await result, 22);
1594
+ },
1595
+ },
1596
+ {
1597
+ name: 'compileProject awaits ambient imported host Promise results with number params',
1598
+ source: [
1599
+ 'declare function fetchNumber(input: number): Promise<number>;',
1600
+ '',
1601
+ 'export async function main(): Promise<number> {',
1602
+ ' return await fetchNumber(20);',
1603
+ '}',
1604
+ '',
1605
+ ].join('\n'),
1606
+ hostFunctions: {
1607
+ 'src/index.ts:fetchNumber': (input: unknown) => Promise.resolve(Number(input) + 2),
1608
+ },
1609
+ run: async (exported) => {
1610
+ const result = exported();
1611
+ if (!(result instanceof Promise)) {
1612
+ throw new Error('Expected exported async ambient import with params to return a host Promise.');
1613
+ }
1614
+ assertEquals(await result, 22);
1615
+ },
1616
+ },
1617
+ {
1618
+ name: 'compileProject awaits ambient imported host Promise results with string params',
1619
+ source: [
1620
+ 'declare function fetchNumber(input: string): Promise<number>;',
1621
+ '',
1622
+ 'export async function main(): Promise<number> {',
1623
+ ' return await fetchNumber("20");',
1624
+ '}',
1625
+ '',
1626
+ ].join('\n'),
1627
+ hostFunctions: {
1628
+ 'src/index.ts:fetchNumber': (input: unknown) => Promise.resolve(Number(String(input)) + 2),
1629
+ },
1630
+ run: async (exported) => {
1631
+ const result = exported();
1632
+ if (!(result instanceof Promise)) {
1633
+ throw new Error('Expected exported async ambient string import to return a host Promise.');
1634
+ }
1635
+ assertEquals(await result, 22);
1636
+ },
1637
+ },
1638
+ {
1639
+ name: 'compileProject awaits ambient imported host Promise results with Promise params',
1640
+ source: [
1641
+ 'declare function fetchNumber(input: Promise<number>): Promise<number>;',
1642
+ '',
1643
+ 'export async function main(): Promise<number> {',
1644
+ ' return await fetchNumber(Promise.resolve(20));',
1645
+ '}',
1646
+ '',
1647
+ ].join('\n'),
1648
+ hostFunctions: {
1649
+ 'src/index.ts:fetchNumber': async (input: unknown) => Number(await (input as Promise<unknown>)) + 2,
1650
+ },
1651
+ run: async (exported) => {
1652
+ const result = exported();
1653
+ if (!(result instanceof Promise)) {
1654
+ throw new Error('Expected exported async ambient Promise-param import to return a host Promise.');
1655
+ }
1656
+ assertEquals(await result, 22);
1657
+ },
1658
+ },
1659
+ {
1660
+ name: 'compileProject awaits host Promise parameters through exported Promise boundaries',
1661
+ source: [
1662
+ 'async function compute(input: Promise<number>): Promise<number> {',
1663
+ ' const value = await input;',
1664
+ ' return value + 2;',
1665
+ '}',
1666
+ '',
1667
+ 'export function main(input: Promise<number>): Promise<number> {',
1668
+ ' return compute(input);',
1669
+ '}',
1670
+ '',
1671
+ ].join('\n'),
1672
+ run: async (exported) => {
1673
+ const result = exported(Promise.resolve(20));
1674
+ if (!(result instanceof Promise)) {
1675
+ throw new Error('Expected exported Promise boundary to return a host Promise.');
1676
+ }
1677
+ assertEquals(await result, 22);
1678
+ },
1679
+ },
1680
+ {
1681
+ name: 'compileProject propagates rejected host Promise parameters through exported Promise boundaries',
1682
+ source: [
1683
+ 'async function compute(input: Promise<number>): Promise<number> {',
1684
+ ' return await input;',
1685
+ '}',
1686
+ '',
1687
+ 'export function main(input: Promise<number>): Promise<number> {',
1688
+ ' return compute(input);',
1689
+ '}',
1690
+ '',
1691
+ ].join('\n'),
1692
+ run: async (exported) => {
1693
+ const result = exported(Promise.reject(20));
1694
+ if (!(result instanceof Promise)) {
1695
+ throw new Error('Expected exported Promise boundary to return a host Promise.');
1696
+ }
1697
+ try {
1698
+ await result;
1699
+ throw new Error('Expected bridged host Promise rejection.');
1700
+ } catch (error) {
1701
+ assertEquals(error, 20);
1702
+ }
1703
+ },
1704
+ },
1705
+ {
1706
+ name: 'compileProject bridges exported async try/catch over host Promise rejections',
1707
+ source: [
1708
+ 'export async function main(input: Promise<number>): Promise<number> {',
1709
+ ' try {',
1710
+ ' return await input;',
1711
+ ' } catch {',
1712
+ ' return 22;',
1713
+ ' }',
1714
+ '}',
1715
+ '',
1716
+ ].join('\n'),
1717
+ run: async (exported) => {
1718
+ const result = exported(Promise.reject(20));
1719
+ if (!(result instanceof Promise)) {
1720
+ throw new Error('Expected exported async try/catch to return a host Promise.');
1721
+ }
1722
+ assertEquals(await result, 22);
1723
+ },
1724
+ },
1725
+ {
1726
+ name: 'compileProject bridges exported async try/finally with return inside finally',
1727
+ source: [
1728
+ 'export async function main(input: Promise<number>): Promise<number> {',
1729
+ ' try {',
1730
+ ' return await input;',
1731
+ ' } finally {',
1732
+ ' return 22;',
1733
+ ' }',
1734
+ '}',
1735
+ '',
1736
+ ].join('\n'),
1737
+ run: async (exported) => {
1738
+ const result = exported(Promise.reject(20));
1739
+ if (!(result instanceof Promise)) {
1740
+ throw new Error('Expected exported async try/finally to return a host Promise.');
1741
+ }
1742
+ assertEquals(await result, 22);
1743
+ },
1744
+ },
1745
+ {
1746
+ name: 'compileProject bridges exported async try/catch with catch bindings',
1747
+ source: [
1748
+ 'export async function main(input: Promise<number>): Promise<number> {',
1749
+ ' try {',
1750
+ ' return await input;',
1751
+ ' } catch (error: unknown) {',
1752
+ ' return 22;',
1753
+ ' }',
1754
+ '}',
1755
+ '',
1756
+ ].join('\n'),
1757
+ run: async (exported) => {
1758
+ const result = exported(Promise.reject('boom'));
1759
+ if (!(result instanceof Promise)) {
1760
+ throw new Error('Expected exported async try/catch to return a host Promise.');
1761
+ }
1762
+ assertEquals(await result, 22);
1763
+ },
1764
+ },
1765
+ {
1766
+ name: 'compileProject lowers async throw statements through compiler-owned Promise rejection',
1767
+ expectedObserved: 22,
1768
+ reducer: 'last',
1769
+ source: [
1770
+ 'export function main(callback: (value: number) => number): number {',
1771
+ ' async function run(): Promise<number> {',
1772
+ ' throw new Error("boom");',
1773
+ ' }',
1774
+ ' run()',
1775
+ ' .catch(() => {',
1776
+ ' callback(22);',
1777
+ ' return 0;',
1778
+ ' });',
1779
+ ' return 0;',
1780
+ '}',
1781
+ '',
1782
+ ].join('\n'),
1783
+ run: async (exported) => {
1784
+ let observed = 0;
1785
+ assertEquals(
1786
+ exported((value: number) => {
1787
+ observed = value;
1788
+ return value;
1789
+ }),
1790
+ 0,
1791
+ );
1792
+ assertEquals(observed, 22);
1793
+ },
1794
+ },
1795
+ {
1796
+ name: 'compileProject bridges exported async throw statements to host Promise rejection',
1797
+ source: [
1798
+ 'export async function main(): Promise<number> {',
1799
+ ' throw new Error("boom");',
1800
+ '}',
1801
+ '',
1802
+ ].join('\n'),
1803
+ run: async (exported) => {
1804
+ const result = exported();
1805
+ if (!(result instanceof Promise)) {
1806
+ throw new Error('Expected exported async throw to return a host Promise.');
1807
+ }
1808
+ const observed = await result.then(() => 0, () => 22);
1809
+ assertEquals(observed, 22);
1810
+ },
1811
+ },
1812
+ {
1813
+ name: 'compileProject lowers async throw statements from builtin Error parameters',
1814
+ expectedObserved: 22,
1815
+ reducer: 'last',
1816
+ source: [
1817
+ 'export function main(callback: (value: number) => number): number {',
1818
+ ' async function run(reason: Error): Promise<number> {',
1819
+ ' throw reason;',
1820
+ ' }',
1821
+ ' run(new Error("boom"))',
1822
+ ' .catch(() => {',
1823
+ ' callback(22);',
1824
+ ' return 0;',
1825
+ ' });',
1826
+ ' return 0;',
1827
+ '}',
1828
+ '',
1829
+ ].join('\n'),
1830
+ run: async (exported) => {
1831
+ let observed = 0;
1832
+ assertEquals(
1833
+ exported((value: number) => {
1834
+ observed = value;
1835
+ return value;
1836
+ }),
1837
+ 0,
1838
+ );
1839
+ assertEquals(observed, 22);
1840
+ },
1841
+ },
1842
+ {
1843
+ name: 'compileProject lowers async throw statements from inferred builtin Error locals',
1844
+ expectedObserved: 22,
1845
+ reducer: 'last',
1846
+ source: [
1847
+ 'export function main(callback: (value: number) => number): number {',
1848
+ ' async function run(): Promise<number> {',
1849
+ ' const reason = new Error("boom");',
1850
+ ' throw reason;',
1851
+ ' }',
1852
+ ' run()',
1853
+ ' .catch(() => {',
1854
+ ' callback(22);',
1855
+ ' return 0;',
1856
+ ' });',
1857
+ ' return 0;',
1858
+ '}',
1859
+ '',
1860
+ ].join('\n'),
1861
+ run: async (exported) => {
1862
+ let observed = 0;
1863
+ assertEquals(
1864
+ exported((value: number) => {
1865
+ observed = value;
1866
+ return value;
1867
+ }),
1868
+ 0,
1869
+ );
1870
+ assertEquals(observed, 22);
1871
+ },
1872
+ },
1873
+ {
1874
+ name: 'compileProject lowers async throw statements from annotated builtin Error locals',
1875
+ expectedObserved: 22,
1876
+ reducer: 'last',
1877
+ source: [
1878
+ 'export function main(callback: (value: number) => number): number {',
1879
+ ' async function run(): Promise<number> {',
1880
+ ' let reason: Error = new Error("boom");',
1881
+ ' throw reason;',
1882
+ ' }',
1883
+ ' run()',
1884
+ ' .catch(() => {',
1885
+ ' callback(22);',
1886
+ ' return 0;',
1887
+ ' });',
1888
+ ' return 0;',
1889
+ '}',
1890
+ '',
1891
+ ].join('\n'),
1892
+ run: async (exported) => {
1893
+ let observed = 0;
1894
+ assertEquals(
1895
+ exported((value: number) => {
1896
+ observed = value;
1897
+ return value;
1898
+ }),
1899
+ 0,
1900
+ );
1901
+ assertEquals(observed, 22);
1902
+ },
1903
+ },
1904
+ {
1905
+ name: 'compileProject lowers async catch rethrow after builtin Error instanceof narrowing',
1906
+ expectedObserved: 23,
1907
+ reducer: 'last',
1908
+ source: [
1909
+ 'export function main(callback: (value: number) => number): number {',
1910
+ ' async function compute(): Promise<number> {',
1911
+ ' const rejected: Promise<number> = Promise.reject(new Error("boom"));',
1912
+ ' try {',
1913
+ ' return await rejected;',
1914
+ ' } catch (error: unknown) {',
1915
+ ' if (error instanceof Error) {',
1916
+ ' throw error;',
1917
+ ' }',
1918
+ ' return 21;',
1919
+ ' }',
1920
+ ' }',
1921
+ ' compute().catch(() => {',
1922
+ ' callback(23);',
1923
+ ' return 0;',
1924
+ ' });',
1925
+ ' return 0;',
1926
+ '}',
1927
+ '',
1928
+ ].join('\n'),
1929
+ run: async (exported) => {
1930
+ let observed = 0;
1931
+ assertEquals(
1932
+ exported((value: number) => {
1933
+ observed = value;
1934
+ return value;
1935
+ }),
1936
+ 0,
1937
+ );
1938
+ assertEquals(observed, 23);
1939
+ },
1940
+ },
1941
+ {
1942
+ name: 'compileProject lowers direct await Promise.reject builtin Error catch rethrow',
1943
+ expectedObserved: 23,
1944
+ reducer: 'last',
1945
+ source: [
1946
+ 'export function main(callback: (value: number) => number): number {',
1947
+ ' async function compute(): Promise<number> {',
1948
+ ' try {',
1949
+ ' return await Promise.reject(new Error("boom"));',
1950
+ ' } catch (error: unknown) {',
1951
+ ' if (error instanceof Error) {',
1952
+ ' throw error;',
1953
+ ' }',
1954
+ ' return 21;',
1955
+ ' }',
1956
+ ' }',
1957
+ ' compute().catch(() => {',
1958
+ ' callback(23);',
1959
+ ' return 0;',
1960
+ ' });',
1961
+ ' return 0;',
1962
+ '}',
1963
+ '',
1964
+ ].join('\n'),
1965
+ run: async (exported) => {
1966
+ let observed = 0;
1967
+ assertEquals(
1968
+ exported((value: number) => {
1969
+ observed = value;
1970
+ return value;
1971
+ }),
1972
+ 0,
1973
+ );
1974
+ assertEquals(observed, 23);
1975
+ },
1976
+ },
1977
+ {
1978
+ name: 'compileProject bridges exported async builtin Error catch rethrow to host Promise rejection',
1979
+ source: [
1980
+ 'export async function main(): Promise<number> {',
1981
+ ' try {',
1982
+ ' return await Promise.reject(new Error("boom"));',
1983
+ ' } catch (error: unknown) {',
1984
+ ' if (error instanceof Error) {',
1985
+ ' throw error;',
1986
+ ' }',
1987
+ ' return 21;',
1988
+ ' }',
1989
+ '}',
1990
+ '',
1991
+ ].join('\n'),
1992
+ run: async (exported) => {
1993
+ const result = exported();
1994
+ if (!(result instanceof Promise)) {
1995
+ throw new Error('Expected exported async builtin Error rethrow to return a host Promise.');
1996
+ }
1997
+ const observed = await result.then(() => 0, () => 22);
1998
+ assertEquals(observed, 22);
1999
+ },
2000
+ },
2001
+ {
2002
+ name: 'compileProject bridges host Promise builtin Error catch rethrow through exported async functions',
2003
+ source: [
2004
+ 'export async function main(input: Promise<number>): Promise<number> {',
2005
+ ' try {',
2006
+ ' return await input;',
2007
+ ' } catch (error: unknown) {',
2008
+ ' if (error instanceof Error) {',
2009
+ ' throw error;',
2010
+ ' }',
2011
+ ' return 21;',
2012
+ ' }',
2013
+ '}',
2014
+ '',
2015
+ ].join('\n'),
2016
+ run: async (exported) => {
2017
+ const result = exported(Promise.reject(new Error('boom')));
2018
+ if (!(result instanceof Promise)) {
2019
+ throw new Error('Expected exported async host Promise Error rethrow to return a host Promise.');
2020
+ }
2021
+ const observed = await result.then(() => 0, () => 22);
2022
+ assertEquals(observed, 22);
2023
+ },
2024
+ },
2025
+ {
2026
+ name: 'compileProject bridges exported async if branches with awaited mutable locals',
2027
+ source: [
2028
+ 'export async function main(flag: boolean): Promise<number> {',
2029
+ ' let total = 0;',
2030
+ ' if (flag) {',
2031
+ ' total = await Promise.resolve(20);',
2032
+ ' } else {',
2033
+ ' total = await Promise.resolve(21);',
2034
+ ' }',
2035
+ ' return flag ? total + 2 : total + 1;',
2036
+ '}',
2037
+ '',
2038
+ ].join('\n'),
2039
+ run: async (exported) => {
2040
+ const trueResult = exported(true);
2041
+ if (!(trueResult instanceof Promise)) {
2042
+ throw new Error('Expected exported async if branch to return a host Promise.');
2043
+ }
2044
+ assertEquals(await trueResult, 22);
2045
+ const falseResult = exported(false);
2046
+ if (!(falseResult instanceof Promise)) {
2047
+ throw new Error('Expected exported async if branch to return a host Promise.');
2048
+ }
2049
+ assertEquals(await falseResult, 22);
2050
+ },
2051
+ },
2052
+ {
2053
+ name: 'compileProject bridges exported async non-final try/catch with mutable locals',
2054
+ source: [
2055
+ 'export async function main(): Promise<number> {',
2056
+ ' let total = 0;',
2057
+ ' try {',
2058
+ ' total = await Promise.reject<number>(20);',
2059
+ ' } catch {',
2060
+ ' total = 20;',
2061
+ ' }',
2062
+ ' return total + 2;',
2063
+ '}',
2064
+ '',
2065
+ ].join('\n'),
2066
+ run: async (exported) => {
2067
+ const result = exported();
2068
+ if (!(result instanceof Promise)) {
2069
+ throw new Error('Expected exported async try/catch to return a host Promise.');
2070
+ }
2071
+ assertEquals(await result, 22);
2072
+ },
2073
+ },
2074
+ {
2075
+ name:
2076
+ 'compileProject executes new Promise executors synchronously and fulfills through resolve',
2077
+ expectedObserved: 122,
2078
+ reducer: 'weighted',
2079
+ source: [
2080
+ 'export function main(callback: (value: number) => number): number {',
2081
+ ' new Promise<number>((resolve) => {',
2082
+ ' callback(1);',
2083
+ ' resolve(20);',
2084
+ ' }).then((value) => {',
2085
+ ' callback(value + 2);',
2086
+ ' return value + 3;',
2087
+ ' });',
2088
+ ' return 0;',
2089
+ '}',
2090
+ '',
2091
+ ].join('\n'),
2092
+ },
2093
+ {
2094
+ name: 'compileProject rejects through new Promise reject callbacks',
2095
+ expectedObserved: 122,
2096
+ reducer: 'weighted',
2097
+ source: [
2098
+ 'export function main(callback: (value: number) => number): number {',
2099
+ ' new Promise<number>((_, reject) => {',
2100
+ ' callback(1);',
2101
+ ' reject(20);',
2102
+ ' }).catch(() => {',
2103
+ ' callback(22);',
2104
+ ' return 23;',
2105
+ ' });',
2106
+ ' return 0;',
2107
+ '}',
2108
+ '',
2109
+ ].join('\n'),
2110
+ },
2111
+ {
2112
+ name: 'compileProject executes Promise.finally callbacks and preserves fulfilled values',
2113
+ expectedObserved: 122,
2114
+ reducer: 'weighted',
2115
+ source: [
2116
+ 'export function main(callback: (value: number) => number): number {',
2117
+ ' Promise.resolve(20)',
2118
+ ' .finally(() => {',
2119
+ ' callback(1);',
2120
+ ' })',
2121
+ ' .then((value) => {',
2122
+ ' callback(value + 2);',
2123
+ ' return value + 3;',
2124
+ ' });',
2125
+ ' return 0;',
2126
+ '}',
2127
+ '',
2128
+ ].join('\n'),
2129
+ },
2130
+ {
2131
+ name: 'compileProject executes Promise.finally callbacks and preserves rejected reasons',
2132
+ expectedObserved: 122,
2133
+ reducer: 'weighted',
2134
+ source: [
2135
+ 'export function main(callback: (value: number) => number): number {',
2136
+ ' Promise.reject(20)',
2137
+ ' .finally(() => {',
2138
+ ' callback(1);',
2139
+ ' })',
2140
+ ' .catch(() => {',
2141
+ ' callback(22);',
2142
+ ' return 0;',
2143
+ ' });',
2144
+ ' return 0;',
2145
+ '}',
2146
+ '',
2147
+ ].join('\n'),
2148
+ },
2149
+ {
2150
+ name: 'compileProject treats undefined Promise.finally callbacks as passthrough handlers',
2151
+ expectedObserved: 22,
2152
+ reducer: 'last',
2153
+ source: [
2154
+ 'export function main(callback: (value: number) => number): number {',
2155
+ ' const cleanup = undefined;',
2156
+ ' Promise.resolve(20)',
2157
+ ' .finally(cleanup)',
2158
+ ' .then((value) => {',
2159
+ ' callback(value + 2);',
2160
+ ' return value + 3;',
2161
+ ' });',
2162
+ ' return 0;',
2163
+ '}',
2164
+ '',
2165
+ ].join('\n'),
2166
+ },
2167
+ ];
2168
+ if (Deno.env.get('SOUNDSCRIPT_PROMISE_LIST_CASES') === '1') {
2169
+ console.log(JSON.stringify(cases.map((testCase) => testCase.name)));
2170
+ return;
2171
+ }
2172
+
2173
+ for (const testCase of cases) {
2174
+ if (caseFilters && !caseFilters.has(testCase.name)) {
2175
+ continue;
2176
+ }
2177
+ if (caseFilter && !testCase.name.includes(caseFilter)) {
2178
+ continue;
2179
+ }
2180
+ await runPromiseCompilerCase(testCase);
2181
+ }
2182
+ }
2183
+
2184
+ await main();