@scriptc/compiler 0.4.3 → 0.4.5

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 (852) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +270 -72
  2. package/ambient/scriptc-overrides.d.ts +21 -0
  3. package/dist/backend/executable-features.js +3 -0
  4. package/dist/backend/executable-features.js.map +1 -1
  5. package/dist/backend/library-pack.js +2 -1
  6. package/dist/backend/library-pack.js.map +1 -1
  7. package/dist/backend/linker.js +11 -1
  8. package/dist/backend/linker.js.map +1 -1
  9. package/dist/backend/lld.d.ts +9 -0
  10. package/dist/backend/lld.js +48 -0
  11. package/dist/backend/lld.js.map +1 -0
  12. package/dist/backend/lld.test.d.ts +1 -0
  13. package/dist/backend/lld.test.js +53 -0
  14. package/dist/backend/lld.test.js.map +1 -0
  15. package/dist/backend/llvm/appended-array-literals.d.ts +11 -1
  16. package/dist/backend/llvm/appended-array-literals.js +29 -0
  17. package/dist/backend/llvm/appended-array-literals.js.map +1 -1
  18. package/dist/backend/llvm/blocks.js +10 -1
  19. package/dist/backend/llvm/blocks.js.map +1 -1
  20. package/dist/backend/llvm/bytes-alias.d.ts +13 -4
  21. package/dist/backend/llvm/bytes-alias.js +16 -5
  22. package/dist/backend/llvm/bytes-alias.js.map +1 -1
  23. package/dist/backend/llvm/bytes-bounds.d.ts +5 -1
  24. package/dist/backend/llvm/bytes-bounds.js +199 -2
  25. package/dist/backend/llvm/bytes-bounds.js.map +1 -1
  26. package/dist/backend/llvm/bytes-loop-versions.d.ts +45 -3
  27. package/dist/backend/llvm/bytes-loop-versions.js +244 -20
  28. package/dist/backend/llvm/bytes-loop-versions.js.map +1 -1
  29. package/dist/backend/llvm/bytes-loop-versions.test.js +18 -6
  30. package/dist/backend/llvm/bytes-loop-versions.test.js.map +1 -1
  31. package/dist/backend/llvm/call-lifetimes.d.ts +8 -2
  32. package/dist/backend/llvm/call-lifetimes.js +87 -18
  33. package/dist/backend/llvm/call-lifetimes.js.map +1 -1
  34. package/dist/backend/llvm/call-lifetimes.test.js +132 -0
  35. package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
  36. package/dist/backend/llvm/classes.d.ts +3 -2
  37. package/dist/backend/llvm/classes.js +4 -4
  38. package/dist/backend/llvm/classes.js.map +1 -1
  39. package/dist/backend/llvm/counted-loops.d.ts +14 -2
  40. package/dist/backend/llvm/counted-loops.js +54 -5
  41. package/dist/backend/llvm/counted-loops.js.map +1 -1
  42. package/dist/backend/llvm/debug-info.d.ts +42 -1
  43. package/dist/backend/llvm/debug-info.js +72 -6
  44. package/dist/backend/llvm/debug-info.js.map +1 -1
  45. package/dist/backend/llvm/dense-array-loops.js +2 -2
  46. package/dist/backend/llvm/dense-array-loops.js.map +1 -1
  47. package/dist/backend/llvm/dense-array-loops.test.js +1 -0
  48. package/dist/backend/llvm/dense-array-loops.test.js.map +1 -1
  49. package/dist/backend/llvm/dyn.d.ts +69 -8
  50. package/dist/backend/llvm/dyn.js +396 -49
  51. package/dist/backend/llvm/dyn.js.map +1 -1
  52. package/dist/backend/llvm/emit-function.js +30 -16
  53. package/dist/backend/llvm/emit-function.js.map +1 -1
  54. package/dist/backend/llvm/emit-journal.d.ts +8 -4
  55. package/dist/backend/llvm/emit-journal.js +75 -5
  56. package/dist/backend/llvm/emit-journal.js.map +1 -1
  57. package/dist/backend/llvm/emit-module.d.ts +4 -0
  58. package/dist/backend/llvm/emit-module.js +74 -29
  59. package/dist/backend/llvm/emit-module.js.map +1 -1
  60. package/dist/backend/llvm/emit-statements.js +297 -28
  61. package/dist/backend/llvm/emit-statements.js.map +1 -1
  62. package/dist/backend/llvm/emitter.d.ts +144 -13
  63. package/dist/backend/llvm/emitter.js +523 -92
  64. package/dist/backend/llvm/emitter.js.map +1 -1
  65. package/dist/backend/llvm/emitter.test.js +11 -2
  66. package/dist/backend/llvm/emitter.test.js.map +1 -1
  67. package/dist/backend/llvm/expr-async.js +11 -13
  68. package/dist/backend/llvm/expr-async.js.map +1 -1
  69. package/dist/backend/llvm/expr-bytes.d.ts +6 -4
  70. package/dist/backend/llvm/expr-bytes.js +45 -16
  71. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  72. package/dist/backend/llvm/expr-calls.js +13 -11
  73. package/dist/backend/llvm/expr-calls.js.map +1 -1
  74. package/dist/backend/llvm/expr-containers.d.ts +11 -0
  75. package/dist/backend/llvm/expr-containers.js +101 -9
  76. package/dist/backend/llvm/expr-containers.js.map +1 -1
  77. package/dist/backend/llvm/expr-context.d.ts +3 -0
  78. package/dist/backend/llvm/expr-control.js +83 -0
  79. package/dist/backend/llvm/expr-control.js.map +1 -1
  80. package/dist/backend/llvm/expr-dynamic.d.ts +1 -1
  81. package/dist/backend/llvm/expr-dynamic.js +22 -4
  82. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  83. package/dist/backend/llvm/expr-primitives.js +121 -14
  84. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  85. package/dist/backend/llvm/expr-stream-bridges.js +111 -26
  86. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  87. package/dist/backend/llvm/forked-analysis.d.ts +8 -0
  88. package/dist/backend/llvm/forked-analysis.js +43 -0
  89. package/dist/backend/llvm/forked-analysis.js.map +1 -0
  90. package/dist/backend/llvm/integer-values.d.ts +12 -0
  91. package/dist/backend/llvm/integer-values.js +69 -5
  92. package/dist/backend/llvm/integer-values.js.map +1 -1
  93. package/dist/backend/llvm/integer-views.d.ts +2 -1
  94. package/dist/backend/llvm/integer-views.js +12 -1
  95. package/dist/backend/llvm/integer-views.js.map +1 -1
  96. package/dist/backend/llvm/js-ic.d.ts +4 -0
  97. package/dist/backend/llvm/js-ic.js +133 -15
  98. package/dist/backend/llvm/js-ic.js.map +1 -1
  99. package/dist/backend/llvm/layouts.d.ts +1 -0
  100. package/dist/backend/llvm/layouts.js.map +1 -1
  101. package/dist/backend/llvm/lazy-captures.d.ts +6 -1
  102. package/dist/backend/llvm/lazy-captures.js +10 -5
  103. package/dist/backend/llvm/lazy-captures.js.map +1 -1
  104. package/dist/backend/llvm/lib-abi.d.ts +5 -0
  105. package/dist/backend/llvm/lib-abi.js +19 -0
  106. package/dist/backend/llvm/lib-abi.js.map +1 -1
  107. package/dist/backend/llvm/lib-dispatch.js +249 -33
  108. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  109. package/dist/backend/llvm/lib-filesystem.d.ts +10 -0
  110. package/dist/backend/llvm/lib-filesystem.js +32 -0
  111. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  112. package/dist/backend/llvm/lib-http2.js +2 -2
  113. package/dist/backend/llvm/lib-http2.js.map +1 -1
  114. package/dist/backend/llvm/lib-network.js +2 -0
  115. package/dist/backend/llvm/lib-network.js.map +1 -1
  116. package/dist/backend/llvm/lib-process.js +48 -1
  117. package/dist/backend/llvm/lib-process.js.map +1 -1
  118. package/dist/backend/llvm/lib-shared.js +64 -0
  119. package/dist/backend/llvm/lib-shared.js.map +1 -1
  120. package/dist/backend/llvm/lib-tls.js +28 -3
  121. package/dist/backend/llvm/lib-tls.js.map +1 -1
  122. package/dist/backend/llvm/local-union-storage.test.js +2 -1
  123. package/dist/backend/llvm/local-union-storage.test.js.map +1 -1
  124. package/dist/backend/llvm/loop-array-borrows.d.ts +4 -1
  125. package/dist/backend/llvm/loop-array-borrows.js +11 -5
  126. package/dist/backend/llvm/loop-array-borrows.js.map +1 -1
  127. package/dist/backend/llvm/map-entry-fusion.d.ts +5 -3
  128. package/dist/backend/llvm/map-entry-fusion.js +20 -11
  129. package/dist/backend/llvm/map-entry-fusion.js.map +1 -1
  130. package/dist/backend/llvm/map-entry-fusion.test.js +14 -6
  131. package/dist/backend/llvm/map-entry-fusion.test.js.map +1 -1
  132. package/dist/backend/llvm/map-number-lookup.d.ts +16 -6
  133. package/dist/backend/llvm/map-number-lookup.js +41 -9
  134. package/dist/backend/llvm/map-number-lookup.js.map +1 -1
  135. package/dist/backend/llvm/map-number-lookup.test.js +70 -2
  136. package/dist/backend/llvm/map-number-lookup.test.js.map +1 -1
  137. package/dist/backend/llvm/map-read-lifetimes.d.ts +25 -2
  138. package/dist/backend/llvm/map-read-lifetimes.js +136 -6
  139. package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
  140. package/dist/backend/llvm/map-read-lifetimes.test.js +8 -3
  141. package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -1
  142. package/dist/backend/llvm/nullable-unions.d.ts +5 -0
  143. package/dist/backend/llvm/nullable-unions.js +29 -2
  144. package/dist/backend/llvm/nullable-unions.js.map +1 -1
  145. package/dist/backend/llvm/nullable-unions.test.js +25 -1
  146. package/dist/backend/llvm/nullable-unions.test.js.map +1 -1
  147. package/dist/backend/llvm/publish.js +3 -3
  148. package/dist/backend/llvm/publish.js.map +1 -1
  149. package/dist/backend/llvm/record-union-keys.test.d.ts +1 -0
  150. package/dist/backend/llvm/record-union-keys.test.js +161 -0
  151. package/dist/backend/llvm/record-union-keys.test.js.map +1 -0
  152. package/dist/backend/llvm/reference-effects.js +3 -0
  153. package/dist/backend/llvm/reference-effects.js.map +1 -1
  154. package/dist/backend/llvm/serialized-ir-emission.test.js +2 -0
  155. package/dist/backend/llvm/serialized-ir-emission.test.js.map +1 -1
  156. package/dist/backend/llvm/shapes.d.ts +4 -5
  157. package/dist/backend/llvm/shapes.js +106 -58
  158. package/dist/backend/llvm/shapes.js.map +1 -1
  159. package/dist/backend/llvm/shapes.test.js +14 -2
  160. package/dist/backend/llvm/shapes.test.js.map +1 -1
  161. package/dist/backend/llvm/speculative-integers.d.ts +50 -3
  162. package/dist/backend/llvm/speculative-integers.js +411 -24
  163. package/dist/backend/llvm/speculative-integers.js.map +1 -1
  164. package/dist/backend/llvm/speculative-integers.test.js +103 -1
  165. package/dist/backend/llvm/speculative-integers.test.js.map +1 -1
  166. package/dist/backend/llvm/split.d.ts +10 -1
  167. package/dist/backend/llvm/split.js +243 -59
  168. package/dist/backend/llvm/split.js.map +1 -1
  169. package/dist/backend/llvm/split.test.js +92 -13
  170. package/dist/backend/llvm/split.test.js.map +1 -1
  171. package/dist/backend/llvm/stack-captures.js +1 -5
  172. package/dist/backend/llvm/stack-captures.js.map +1 -1
  173. package/dist/backend/llvm/stack-objects.test.js +3 -2
  174. package/dist/backend/llvm/stack-objects.test.js.map +1 -1
  175. package/dist/backend/llvm/string-lifetimes.test.js +1 -1
  176. package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
  177. package/dist/backend/llvm/string-reads.d.ts +13 -0
  178. package/dist/backend/llvm/string-reads.js +22 -0
  179. package/dist/backend/llvm/string-reads.js.map +1 -1
  180. package/dist/backend/llvm/string-slices.d.ts +36 -2
  181. package/dist/backend/llvm/string-slices.js +308 -12
  182. package/dist/backend/llvm/string-slices.js.map +1 -1
  183. package/dist/backend/llvm/string-slices.test.js +182 -3
  184. package/dist/backend/llvm/string-slices.test.js.map +1 -1
  185. package/dist/backend/llvm/string-unit-versions.d.ts +11 -0
  186. package/dist/backend/llvm/string-unit-versions.js +191 -0
  187. package/dist/backend/llvm/string-unit-versions.js.map +1 -0
  188. package/dist/backend/llvm/string-unit-versions.test.d.ts +1 -0
  189. package/dist/backend/llvm/string-unit-versions.test.js +117 -0
  190. package/dist/backend/llvm/string-unit-versions.test.js.map +1 -0
  191. package/dist/backend/llvm/test-boxed-unions.d.ts +5 -2
  192. package/dist/backend/llvm/test-boxed-unions.js +24 -8
  193. package/dist/backend/llvm/test-boxed-unions.js.map +1 -1
  194. package/dist/backend/llvm/union-repr.d.ts +4 -3
  195. package/dist/backend/llvm/union-repr.js +6 -5
  196. package/dist/backend/llvm/union-repr.js.map +1 -1
  197. package/dist/backend/llvm/unwind-abi.d.ts +52 -0
  198. package/dist/backend/llvm/unwind-abi.js +498 -0
  199. package/dist/backend/llvm/unwind-abi.js.map +1 -0
  200. package/dist/backend/llvm/unwind-abi.test.d.ts +1 -0
  201. package/dist/backend/llvm/unwind-abi.test.js +255 -0
  202. package/dist/backend/llvm/unwind-abi.test.js.map +1 -0
  203. package/dist/backend/llvm/walkers.js +13 -0
  204. package/dist/backend/llvm/walkers.js.map +1 -1
  205. package/dist/backend/llvm/wrapping-sums.d.ts +14 -10
  206. package/dist/backend/llvm/wrapping-sums.js +31 -14
  207. package/dist/backend/llvm/wrapping-sums.js.map +1 -1
  208. package/dist/backend/loop-polls.d.ts +6 -0
  209. package/dist/backend/loop-polls.js +24 -0
  210. package/dist/backend/loop-polls.js.map +1 -1
  211. package/dist/backend/may-throw.js +8 -8
  212. package/dist/backend/may-throw.js.map +1 -1
  213. package/dist/backend/native/contracts.d.ts +12 -2
  214. package/dist/backend/native/executable.js +48 -6
  215. package/dist/backend/native/executable.js.map +1 -1
  216. package/dist/backend/native/library.js +4 -3
  217. package/dist/backend/native/library.js.map +1 -1
  218. package/dist/backend/native/program-shards.d.ts +2 -2
  219. package/dist/backend/native/program-shards.js +2 -2
  220. package/dist/backend/native/program-shards.js.map +1 -1
  221. package/dist/backend/native/runtime-inputs.d.ts +1 -1
  222. package/dist/backend/native/runtime-inputs.js +4 -1
  223. package/dist/backend/native/runtime-inputs.js.map +1 -1
  224. package/dist/backend/native/vendor.d.ts +1 -1
  225. package/dist/backend/native/vendor.js +1 -1
  226. package/dist/backend/native/vendor.js.map +1 -1
  227. package/dist/backend/native-codegen-core.d.ts +5 -3
  228. package/dist/backend/native-codegen-core.js +13 -6
  229. package/dist/backend/native-codegen-core.js.map +1 -1
  230. package/dist/backend/native-codegen.d.ts +3 -1
  231. package/dist/backend/native-codegen.js +4 -3
  232. package/dist/backend/native-codegen.js.map +1 -1
  233. package/dist/backend/native-codegen.test.js +6 -4
  234. package/dist/backend/native-codegen.test.js.map +1 -1
  235. package/dist/backend/native-link-info-core.d.ts +8 -0
  236. package/dist/backend/native-link-info-core.js.map +1 -1
  237. package/dist/backend/native-profile.d.ts +14 -0
  238. package/dist/backend/native-profile.js +28 -0
  239. package/dist/backend/native-profile.js.map +1 -1
  240. package/dist/backend/native-profile.test.js +8 -1
  241. package/dist/backend/native-profile.test.js.map +1 -1
  242. package/dist/backend/native-toolchain.test.js +11 -11
  243. package/dist/backend/native-toolchain.test.js.map +1 -1
  244. package/dist/backend/runtime-abi.d.ts +2 -2
  245. package/dist/backend/runtime-abi.js +2 -2
  246. package/dist/backend/runtime-pack-core.d.ts +3 -1
  247. package/dist/backend/runtime-pack-core.js +2 -0
  248. package/dist/backend/runtime-pack-core.js.map +1 -1
  249. package/dist/backend/runtime-pack-native.d.ts +17 -5
  250. package/dist/backend/runtime-pack-native.js +186 -14
  251. package/dist/backend/runtime-pack-native.js.map +1 -1
  252. package/dist/backend/runtime-pack-native.test.js +160 -3
  253. package/dist/backend/runtime-pack-native.test.js.map +1 -1
  254. package/dist/backend/runtime-pack-targets.test.js +2 -1
  255. package/dist/backend/runtime-pack-targets.test.js.map +1 -1
  256. package/dist/backend/runtime-pack.test.js +2 -1
  257. package/dist/backend/runtime-pack.test.js.map +1 -1
  258. package/dist/backend/target-cpu.d.ts +26 -0
  259. package/dist/backend/target-cpu.js +98 -0
  260. package/dist/backend/target-cpu.js.map +1 -0
  261. package/dist/backend/target-cpu.test.d.ts +1 -0
  262. package/dist/backend/target-cpu.test.js +38 -0
  263. package/dist/backend/target-cpu.test.js.map +1 -0
  264. package/dist/backend/vendor-archives.d.ts +4 -1
  265. package/dist/backend/vendor-archives.js +78 -4
  266. package/dist/backend/vendor-archives.js.map +1 -1
  267. package/dist/backend/vendor-inputs.d.ts +3 -1
  268. package/dist/backend/vendor-inputs.js +3 -1
  269. package/dist/backend/vendor-inputs.js.map +1 -1
  270. package/dist/backend/warm-cache.js +1 -0
  271. package/dist/backend/warm-cache.js.map +1 -1
  272. package/dist/cli/command.js +98 -12
  273. package/dist/cli/command.js.map +1 -1
  274. package/dist/cli/usage.d.ts +25 -1
  275. package/dist/cli/usage.js +40 -3
  276. package/dist/cli/usage.js.map +1 -1
  277. package/dist/compat/fetch-profile.d.ts +15 -6
  278. package/dist/compat/fetch-profile.js +519 -498
  279. package/dist/compat/fetch-profile.js.map +1 -1
  280. package/dist/compile-types.d.ts +14 -0
  281. package/dist/contracts/int32-elements.js +2 -1
  282. package/dist/contracts/int32-elements.js.map +1 -1
  283. package/dist/coverage/report.d.ts +14 -3
  284. package/dist/coverage/report.js +216 -0
  285. package/dist/coverage/report.js.map +1 -1
  286. package/dist/coverage/surface-manifest.js +25 -25
  287. package/dist/coverage/surface-manifest.js.map +1 -1
  288. package/dist/coverage/verdict-cache.d.ts +2 -0
  289. package/dist/coverage/verdict-cache.js +10 -1
  290. package/dist/coverage/verdict-cache.js.map +1 -1
  291. package/dist/diagnostics/diagnostic.d.ts +19 -0
  292. package/dist/diagnostics/diagnostic.js +53 -2
  293. package/dist/diagnostics/diagnostic.js.map +1 -1
  294. package/dist/diagnostics/envelope.d.ts +54 -0
  295. package/dist/diagnostics/envelope.js +7 -1
  296. package/dist/diagnostics/envelope.js.map +1 -1
  297. package/dist/diagnostics/render.d.ts +7 -0
  298. package/dist/diagnostics/render.js +15 -4
  299. package/dist/diagnostics/render.js.map +1 -1
  300. package/dist/executable/executable-cache.d.ts +6 -0
  301. package/dist/executable/executable-cache.js +5 -0
  302. package/dist/executable/executable-cache.js.map +1 -1
  303. package/dist/executable/executable-cache.test.js +3 -0
  304. package/dist/executable/executable-cache.test.js.map +1 -1
  305. package/dist/executable/prepare.js +5 -1
  306. package/dist/executable/prepare.js.map +1 -1
  307. package/dist/frontend/analysis.js +26 -2
  308. package/dist/frontend/analysis.js.map +1 -1
  309. package/dist/frontend/decl-projection.js +105 -10
  310. package/dist/frontend/decl-projection.js.map +1 -1
  311. package/dist/frontend/fork-target.js +67 -1
  312. package/dist/frontend/fork-target.js.map +1 -1
  313. package/dist/frontend/fork-target.test.js +43 -0
  314. package/dist/frontend/fork-target.test.js.map +1 -1
  315. package/dist/frontend/input-tracker.d.ts +4 -1
  316. package/dist/frontend/input-tracker.js +42 -4
  317. package/dist/frontend/input-tracker.js.map +1 -1
  318. package/dist/frontend/input-tracker.test.js +45 -0
  319. package/dist/frontend/input-tracker.test.js.map +1 -1
  320. package/dist/frontend/lowering/abstract-equality.js +38 -1
  321. package/dist/frontend/lowering/abstract-equality.js.map +1 -1
  322. package/dist/frontend/lowering/argument-counts.d.ts +36 -0
  323. package/dist/frontend/lowering/argument-counts.js +201 -0
  324. package/dist/frontend/lowering/argument-counts.js.map +1 -0
  325. package/dist/frontend/lowering/array-values.d.ts +27 -0
  326. package/dist/frontend/lowering/array-values.js +112 -0
  327. package/dist/frontend/lowering/array-values.js.map +1 -1
  328. package/dist/frontend/lowering/binding-analysis.d.ts +3 -0
  329. package/dist/frontend/lowering/binding-analysis.js +9 -3
  330. package/dist/frontend/lowering/binding-analysis.js.map +1 -1
  331. package/dist/frontend/lowering/builtin-namespaces.d.ts +13 -0
  332. package/dist/frontend/lowering/builtin-namespaces.js +238 -0
  333. package/dist/frontend/lowering/builtin-namespaces.js.map +1 -0
  334. package/dist/frontend/lowering/builtins/async-context.d.ts +8 -2
  335. package/dist/frontend/lowering/builtins/async-context.js +62 -3
  336. package/dist/frontend/lowering/builtins/async-context.js.map +1 -1
  337. package/dist/frontend/lowering/builtins/compression.d.ts +4 -3
  338. package/dist/frontend/lowering/builtins/compression.js +86 -5
  339. package/dist/frontend/lowering/builtins/compression.js.map +1 -1
  340. package/dist/frontend/lowering/builtins/crypto.js +3 -1
  341. package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
  342. package/dist/frontend/lowering/builtins/date-classes.js +17 -1
  343. package/dist/frontend/lowering/builtins/date-classes.js.map +1 -1
  344. package/dist/frontend/lowering/builtins/dates.d.ts +19 -5
  345. package/dist/frontend/lowering/builtins/dates.js +163 -9
  346. package/dist/frontend/lowering/builtins/dates.js.map +1 -1
  347. package/dist/frontend/lowering/builtins/filesystem-calls.js +29 -4
  348. package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
  349. package/dist/frontend/lowering/builtins/fs-glob.js +6 -3
  350. package/dist/frontend/lowering/builtins/fs-glob.js.map +1 -1
  351. package/dist/frontend/lowering/builtins/fs-paths.d.ts +43 -5
  352. package/dist/frontend/lowering/builtins/fs-paths.js +245 -93
  353. package/dist/frontend/lowering/builtins/fs-paths.js.map +1 -1
  354. package/dist/frontend/lowering/builtins/fs-streams.d.ts +4 -0
  355. package/dist/frontend/lowering/builtins/fs-streams.js +24 -1
  356. package/dist/frontend/lowering/builtins/fs-streams.js.map +1 -1
  357. package/dist/frontend/lowering/builtins/json.d.ts +4 -1
  358. package/dist/frontend/lowering/builtins/json.js +9 -3
  359. package/dist/frontend/lowering/builtins/json.js.map +1 -1
  360. package/dist/frontend/lowering/builtins/module-bindings.d.ts +6 -0
  361. package/dist/frontend/lowering/builtins/module-bindings.js +23 -1
  362. package/dist/frontend/lowering/builtins/module-bindings.js.map +1 -1
  363. package/dist/frontend/lowering/builtins/module-calls.js +6 -3
  364. package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
  365. package/dist/frontend/lowering/builtins/module-resolution.d.ts +5 -0
  366. package/dist/frontend/lowering/builtins/module-resolution.js +95 -4
  367. package/dist/frontend/lowering/builtins/module-resolution.js.map +1 -1
  368. package/dist/frontend/lowering/builtins/promises.d.ts +1 -1
  369. package/dist/frontend/lowering/builtins/promises.js +293 -139
  370. package/dist/frontend/lowering/builtins/promises.js.map +1 -1
  371. package/dist/frontend/lowering/builtins/readline.d.ts +5 -1
  372. package/dist/frontend/lowering/builtins/readline.js +22 -11
  373. package/dist/frontend/lowering/builtins/readline.js.map +1 -1
  374. package/dist/frontend/lowering/builtins/reflection.d.ts +4 -1
  375. package/dist/frontend/lowering/builtins/reflection.js +41 -1
  376. package/dist/frontend/lowering/builtins/reflection.js.map +1 -1
  377. package/dist/frontend/lowering/builtins/text-codecs.js +31 -2
  378. package/dist/frontend/lowering/builtins/text-codecs.js.map +1 -1
  379. package/dist/frontend/lowering/builtins/webassembly.js +4 -1
  380. package/dist/frontend/lowering/builtins/webassembly.js.map +1 -1
  381. package/dist/frontend/lowering/builtins/x509.d.ts +33 -0
  382. package/dist/frontend/lowering/builtins/x509.js +431 -0
  383. package/dist/frontend/lowering/builtins/x509.js.map +1 -0
  384. package/dist/frontend/lowering/call-arguments.js +44 -0
  385. package/dist/frontend/lowering/call-arguments.js.map +1 -1
  386. package/dist/frontend/lowering/call-signatures.js +1 -2
  387. package/dist/frontend/lowering/call-signatures.js.map +1 -1
  388. package/dist/frontend/lowering/cjs-exports-object.js +1 -1
  389. package/dist/frontend/lowering/cjs-exports-object.js.map +1 -1
  390. package/dist/frontend/lowering/cjs-inline-require.d.ts +32 -0
  391. package/dist/frontend/lowering/cjs-inline-require.js +308 -5
  392. package/dist/frontend/lowering/cjs-inline-require.js.map +1 -1
  393. package/dist/frontend/lowering/class-attributes.d.ts +7 -0
  394. package/dist/frontend/lowering/class-attributes.js +52 -10
  395. package/dist/frontend/lowering/class-attributes.js.map +1 -1
  396. package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +23 -0
  397. package/dist/frontend/lowering/class-dynamic-dispatch.js +288 -9
  398. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  399. package/dist/frontend/lowering/class-method-mutations.js +97 -26
  400. package/dist/frontend/lowering/class-method-mutations.js.map +1 -1
  401. package/dist/frontend/lowering/class-method-values.js +71 -1
  402. package/dist/frontend/lowering/class-method-values.js.map +1 -1
  403. package/dist/frontend/lowering/class-protocols.d.ts +25 -0
  404. package/dist/frontend/lowering/class-protocols.js +183 -1
  405. package/dist/frontend/lowering/class-protocols.js.map +1 -1
  406. package/dist/frontend/lowering/class-prototypes.d.ts +8 -0
  407. package/dist/frontend/lowering/class-prototypes.js +83 -2
  408. package/dist/frontend/lowering/class-prototypes.js.map +1 -1
  409. package/dist/frontend/lowering/class-to-primitive.d.ts +5 -0
  410. package/dist/frontend/lowering/class-to-primitive.js +79 -7
  411. package/dist/frontend/lowering/class-to-primitive.js.map +1 -1
  412. package/dist/frontend/lowering/coercions/state.d.ts +1 -0
  413. package/dist/frontend/lowering/coercions/state.js.map +1 -1
  414. package/dist/frontend/lowering/coercions/structural.js +89 -10
  415. package/dist/frontend/lowering/coercions/structural.js.map +1 -1
  416. package/dist/frontend/lowering/coercions/unions.d.ts +4 -2
  417. package/dist/frontend/lowering/coercions/unions.js +13 -6
  418. package/dist/frontend/lowering/coercions/unions.js.map +1 -1
  419. package/dist/frontend/lowering/completion-callbacks.d.ts +4 -0
  420. package/dist/frontend/lowering/completion-callbacks.js +146 -0
  421. package/dist/frontend/lowering/completion-callbacks.js.map +1 -0
  422. package/dist/frontend/lowering/containers/array-callbacks.d.ts +5 -4
  423. package/dist/frontend/lowering/containers/array-callbacks.js +58 -21
  424. package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
  425. package/dist/frontend/lowering/containers/array-construction.d.ts +4 -1
  426. package/dist/frontend/lowering/containers/array-construction.js +107 -9
  427. package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
  428. package/dist/frontend/lowering/containers/array-methods.js +96 -8
  429. package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
  430. package/dist/frontend/lowering/containers/array-pipelines.js +346 -77
  431. package/dist/frontend/lowering/containers/array-pipelines.js.map +1 -1
  432. package/dist/frontend/lowering/containers/bytes.d.ts +25 -17
  433. package/dist/frontend/lowering/containers/bytes.js +453 -45
  434. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  435. package/dist/frontend/lowering/containers/callback-arguments.js +11 -1
  436. package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
  437. package/dist/frontend/lowering/containers/collection-methods.js +12 -0
  438. package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
  439. package/dist/frontend/lowering/containers/indexed-objects.js +73 -25
  440. package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
  441. package/dist/frontend/lowering/containers/iterator-helpers.d.ts +4 -4
  442. package/dist/frontend/lowering/containers/iterator-helpers.js +8 -2
  443. package/dist/frontend/lowering/containers/iterator-helpers.js.map +1 -1
  444. package/dist/frontend/lowering/containers/replacer-params.d.ts +37 -0
  445. package/dist/frontend/lowering/containers/replacer-params.js +294 -0
  446. package/dist/frontend/lowering/containers/replacer-params.js.map +1 -0
  447. package/dist/frontend/lowering/containers/replacer-params.test.d.ts +1 -0
  448. package/dist/frontend/lowering/containers/replacer-params.test.js +61 -0
  449. package/dist/frontend/lowering/containers/replacer-params.test.js.map +1 -0
  450. package/dist/frontend/lowering/containers/string-and-regexp.js +2 -1
  451. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  452. package/dist/frontend/lowering/containers/string-replacement.js +7 -3
  453. package/dist/frontend/lowering/containers/string-replacement.js.map +1 -1
  454. package/dist/frontend/lowering/cycle-initialization.d.ts +4 -2
  455. package/dist/frontend/lowering/cycle-initialization.js +4 -1
  456. package/dist/frontend/lowering/cycle-initialization.js.map +1 -1
  457. package/dist/frontend/lowering/date-values.d.ts +14 -0
  458. package/dist/frontend/lowering/date-values.js +254 -0
  459. package/dist/frontend/lowering/date-values.js.map +1 -0
  460. package/dist/frontend/lowering/deferred-module-initializers.js +16 -8
  461. package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -1
  462. package/dist/frontend/lowering/deferred-module-initializers.test.js +22 -6
  463. package/dist/frontend/lowering/deferred-module-initializers.test.js.map +1 -1
  464. package/dist/frontend/lowering/dispatch-sites.js +1 -0
  465. package/dist/frontend/lowering/dispatch-sites.js.map +1 -1
  466. package/dist/frontend/lowering/expressions/array-literals.d.ts +0 -8
  467. package/dist/frontend/lowering/expressions/array-literals.js +125 -26
  468. package/dist/frontend/lowering/expressions/array-literals.js.map +1 -1
  469. package/dist/frontend/lowering/expressions/binary.js +102 -26
  470. package/dist/frontend/lowering/expressions/binary.js.map +1 -1
  471. package/dist/frontend/lowering/expressions/element-access.js +129 -6
  472. package/dist/frontend/lowering/expressions/element-access.js.map +1 -1
  473. package/dist/frontend/lowering/expressions/identifiers.js +66 -4
  474. package/dist/frontend/lowering/expressions/identifiers.js.map +1 -1
  475. package/dist/frontend/lowering/expressions/narrowing.d.ts +2 -1
  476. package/dist/frontend/lowering/expressions/narrowing.js +8 -1
  477. package/dist/frontend/lowering/expressions/narrowing.js.map +1 -1
  478. package/dist/frontend/lowering/expressions/object-literals.js +8 -2
  479. package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
  480. package/dist/frontend/lowering/expressions/property-access.js +121 -34
  481. package/dist/frontend/lowering/expressions/property-access.js.map +1 -1
  482. package/dist/frontend/lowering/expressions/relational.js +76 -11
  483. package/dist/frontend/lowering/expressions/relational.js.map +1 -1
  484. package/dist/frontend/lowering/expressions/typeof.js +12 -1
  485. package/dist/frontend/lowering/expressions/typeof.js.map +1 -1
  486. package/dist/frontend/lowering/expressions/updates.js +37 -11
  487. package/dist/frontend/lowering/expressions/updates.js.map +1 -1
  488. package/dist/frontend/lowering/f64-handles.d.ts +8 -0
  489. package/dist/frontend/lowering/f64-handles.js +16 -0
  490. package/dist/frontend/lowering/f64-handles.js.map +1 -0
  491. package/dist/frontend/lowering/frozen-records.d.ts +5 -0
  492. package/dist/frontend/lowering/frozen-records.js +12 -4
  493. package/dist/frontend/lowering/frozen-records.js.map +1 -1
  494. package/dist/frontend/lowering/function-context.d.ts +3 -0
  495. package/dist/frontend/lowering/function-context.js.map +1 -1
  496. package/dist/frontend/lowering/function-returns.js +30 -0
  497. package/dist/frontend/lowering/function-returns.js.map +1 -1
  498. package/dist/frontend/lowering/generic-functions.js +17 -6
  499. package/dist/frontend/lowering/generic-functions.js.map +1 -1
  500. package/dist/frontend/lowering/indexed-unions.d.ts +54 -0
  501. package/dist/frontend/lowering/indexed-unions.js +401 -0
  502. package/dist/frontend/lowering/indexed-unions.js.map +1 -0
  503. package/dist/frontend/lowering/instantiation-path.d.ts +3 -2
  504. package/dist/frontend/lowering/instantiation-path.js.map +1 -1
  505. package/dist/frontend/lowering/instantiation-path.test.js +6 -4
  506. package/dist/frontend/lowering/instantiation-path.test.js.map +1 -1
  507. package/dist/frontend/lowering/iterator-adapters.d.ts +4 -2
  508. package/dist/frontend/lowering/iterator-adapters.js +26 -33
  509. package/dist/frontend/lowering/iterator-adapters.js.map +1 -1
  510. package/dist/frontend/lowering/js-collection-types.d.ts +11 -0
  511. package/dist/frontend/lowering/js-collection-types.js +490 -0
  512. package/dist/frontend/lowering/js-collection-types.js.map +1 -0
  513. package/dist/frontend/lowering/key-order-witness.js +210 -32
  514. package/dist/frontend/lowering/key-order-witness.js.map +1 -1
  515. package/dist/frontend/lowering/key-order-witness.test.js +104 -4
  516. package/dist/frontend/lowering/key-order-witness.test.js.map +1 -1
  517. package/dist/frontend/lowering/lib-boundary.js +2 -2
  518. package/dist/frontend/lowering/lib-boundary.js.map +1 -1
  519. package/dist/frontend/lowering/lower-assert.d.ts +14 -0
  520. package/dist/frontend/lowering/lower-assert.js +298 -29
  521. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  522. package/dist/frontend/lowering/lower-builtin-values.js +3 -3
  523. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
  524. package/dist/frontend/lowering/lower-calls.js +116 -10
  525. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  526. package/dist/frontend/lowering/lower-classes.d.ts +59 -7
  527. package/dist/frontend/lowering/lower-classes.js +668 -222
  528. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  529. package/dist/frontend/lowering/lower-console.js +2 -1
  530. package/dist/frontend/lowering/lower-console.js.map +1 -1
  531. package/dist/frontend/lowering/lower-exprs.d.ts +5 -0
  532. package/dist/frontend/lowering/lower-exprs.js +254 -3
  533. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  534. package/dist/frontend/lowering/lower-functions.js +7 -0
  535. package/dist/frontend/lowering/lower-functions.js.map +1 -1
  536. package/dist/frontend/lowering/lower-generators.js +5 -4
  537. package/dist/frontend/lowering/lower-generators.js.map +1 -1
  538. package/dist/frontend/lowering/lower-inspect.d.ts +1 -1
  539. package/dist/frontend/lowering/lower-inspect.js +299 -57
  540. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  541. package/dist/frontend/lowering/lower-modules.js +49 -22
  542. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  543. package/dist/frontend/lowering/lower-namespaces.d.ts +3 -0
  544. package/dist/frontend/lowering/lower-namespaces.js +44 -1
  545. package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
  546. package/dist/frontend/lowering/lower-node-module.js +1 -1
  547. package/dist/frontend/lowering/lower-node-module.js.map +1 -1
  548. package/dist/frontend/lowering/lower-server.js +126 -32
  549. package/dist/frontend/lowering/lower-server.js.map +1 -1
  550. package/dist/frontend/lowering/lower-stdlib.d.ts +4 -1
  551. package/dist/frontend/lowering/lower-stdlib.js +51 -37
  552. package/dist/frontend/lowering/lower-stdlib.js.map +1 -1
  553. package/dist/frontend/lowering/lower-stmts.js +393 -79
  554. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  555. package/dist/frontend/lowering/lower-stream.js +515 -121
  556. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  557. package/dist/frontend/lowering/lowerer.d.ts +82 -12
  558. package/dist/frontend/lowering/lowerer.js +317 -44
  559. package/dist/frontend/lowering/lowerer.js.map +1 -1
  560. package/dist/frontend/lowering/lowerer.test.js +1 -1
  561. package/dist/frontend/lowering/lowerer.test.js.map +1 -1
  562. package/dist/frontend/lowering/module-namespace-elements.d.ts +13 -0
  563. package/dist/frontend/lowering/module-namespace-elements.js +118 -1
  564. package/dist/frontend/lowering/module-namespace-elements.js.map +1 -1
  565. package/dist/frontend/lowering/object-factory-new.d.ts +5 -0
  566. package/dist/frontend/lowering/object-factory-new.js +20 -6
  567. package/dist/frontend/lowering/object-factory-new.js.map +1 -1
  568. package/dist/frontend/lowering/overload-choice.d.ts +33 -0
  569. package/dist/frontend/lowering/overload-choice.js +190 -0
  570. package/dist/frontend/lowering/overload-choice.js.map +1 -0
  571. package/dist/frontend/lowering/private-brands.d.ts +5 -0
  572. package/dist/frontend/lowering/private-brands.js +39 -0
  573. package/dist/frontend/lowering/private-brands.js.map +1 -1
  574. package/dist/frontend/lowering/runtime-optional-elements.d.ts +6 -0
  575. package/dist/frontend/lowering/runtime-optional-elements.js +14 -3
  576. package/dist/frontend/lowering/runtime-optional-elements.js.map +1 -1
  577. package/dist/frontend/lowering/sanitize-class-types.js +2 -0
  578. package/dist/frontend/lowering/sanitize-class-types.js.map +1 -1
  579. package/dist/frontend/lowering/site-dependencies.d.ts +7 -2
  580. package/dist/frontend/lowering/site-dependencies.js +0 -15
  581. package/dist/frontend/lowering/site-dependencies.js.map +1 -1
  582. package/dist/frontend/lowering/site-dependencies.test.js +7 -5
  583. package/dist/frontend/lowering/site-dependencies.test.js.map +1 -1
  584. package/dist/frontend/lowering/string-index-bounds.d.ts +7 -4
  585. package/dist/frontend/lowering/string-index-bounds.js +21 -7
  586. package/dist/frontend/lowering/string-index-bounds.js.map +1 -1
  587. package/dist/frontend/lowering/surfaces.d.ts +12 -3
  588. package/dist/frontend/lowering/surfaces.js +1630 -1540
  589. package/dist/frontend/lowering/surfaces.js.map +1 -1
  590. package/dist/frontend/lowering/symbol-fields.d.ts +7 -0
  591. package/dist/frontend/lowering/symbol-fields.js +45 -2
  592. package/dist/frontend/lowering/symbol-fields.js.map +1 -1
  593. package/dist/frontend/lowering/union-narrow.d.ts +5 -2
  594. package/dist/frontend/lowering/union-narrow.js +6 -3
  595. package/dist/frontend/lowering/union-narrow.js.map +1 -1
  596. package/dist/frontend/lowering/union-narrow.test.js +10 -0
  597. package/dist/frontend/lowering/union-narrow.test.js.map +1 -1
  598. package/dist/frontend/npm-static-namespace-defaults.d.ts +6 -0
  599. package/dist/frontend/npm-static-namespace-defaults.js +163 -0
  600. package/dist/frontend/npm-static-namespace-defaults.js.map +1 -0
  601. package/dist/frontend/npm-static-namespace-defaults.test.d.ts +1 -0
  602. package/dist/frontend/npm-static-namespace-defaults.test.js +72 -0
  603. package/dist/frontend/npm-static-namespace-defaults.test.js.map +1 -0
  604. package/dist/frontend/npm-static-prune.js +152 -111
  605. package/dist/frontend/npm-static-prune.js.map +1 -1
  606. package/dist/frontend/npm-static.js +35 -32
  607. package/dist/frontend/npm-static.js.map +1 -1
  608. package/dist/frontend/package-shims.d.ts +7 -4
  609. package/dist/frontend/package-shims.js +39 -40
  610. package/dist/frontend/package-shims.js.map +1 -1
  611. package/dist/frontend/pipeline-native.d.ts +2 -2
  612. package/dist/frontend/pipeline-native.js +2 -2
  613. package/dist/frontend/pipeline-native.js.map +1 -1
  614. package/dist/frontend/pipeline.d.ts +19 -2
  615. package/dist/frontend/pipeline.js +103 -12
  616. package/dist/frontend/pipeline.js.map +1 -1
  617. package/dist/frontend/program-analysis.d.ts +7 -1
  618. package/dist/frontend/program-analysis.js +8 -0
  619. package/dist/frontend/program-analysis.js.map +1 -1
  620. package/dist/frontend/program.d.ts +28 -5
  621. package/dist/frontend/program.js +422 -76
  622. package/dist/frontend/program.js.map +1 -1
  623. package/dist/frontend/resolve.d.ts +2 -0
  624. package/dist/frontend/resolve.js +5 -0
  625. package/dist/frontend/resolve.js.map +1 -1
  626. package/dist/frontend/services.d.ts +3 -0
  627. package/dist/frontend/services.js +31 -4
  628. package/dist/frontend/services.js.map +1 -1
  629. package/dist/frontend/shape-inference/analyze.d.ts +93 -0
  630. package/dist/frontend/shape-inference/analyze.js +3138 -0
  631. package/dist/frontend/shape-inference/analyze.js.map +1 -0
  632. package/dist/frontend/shape-inference/constant-graphs.d.ts +54 -0
  633. package/dist/frontend/shape-inference/constant-graphs.js +357 -0
  634. package/dist/frontend/shape-inference/constant-graphs.js.map +1 -0
  635. package/dist/frontend/shape-inference/domain.d.ts +32 -0
  636. package/dist/frontend/shape-inference/domain.js +104 -0
  637. package/dist/frontend/shape-inference/domain.js.map +1 -0
  638. package/dist/frontend/shape-inference/index.d.ts +7 -0
  639. package/dist/frontend/shape-inference/index.js +19 -0
  640. package/dist/frontend/shape-inference/index.js.map +1 -0
  641. package/dist/frontend/shape-inference/report.d.ts +21 -0
  642. package/dist/frontend/shape-inference/report.js +348 -0
  643. package/dist/frontend/shape-inference/report.js.map +1 -0
  644. package/dist/frontend/token-equivalence.d.ts +6 -0
  645. package/dist/frontend/token-equivalence.js +66 -9
  646. package/dist/frontend/token-equivalence.js.map +1 -1
  647. package/dist/frontend/token-equivalence.test.js +33 -1
  648. package/dist/frontend/token-equivalence.test.js.map +1 -1
  649. package/dist/frontend/ts7/checker-features.d.ts +15 -0
  650. package/dist/frontend/ts7/checker-features.js +45 -0
  651. package/dist/frontend/ts7/checker-features.js.map +1 -0
  652. package/dist/frontend/ts7/checker-features.test.d.ts +1 -0
  653. package/dist/frontend/ts7/checker-features.test.js +40 -0
  654. package/dist/frontend/ts7/checker-features.test.js.map +1 -0
  655. package/dist/frontend/ts7/checker-server.d.ts +19 -0
  656. package/dist/frontend/ts7/checker-server.js +46 -0
  657. package/dist/frontend/ts7/checker-server.js.map +1 -0
  658. package/dist/frontend/ts7/checker-server.test.d.ts +1 -0
  659. package/dist/frontend/ts7/checker-server.test.js +38 -0
  660. package/dist/frontend/ts7/checker-server.test.js.map +1 -0
  661. package/dist/frontend/ts7/lib-diagnostics.js +39 -13
  662. package/dist/frontend/ts7/lib-diagnostics.js.map +1 -1
  663. package/dist/frontend/ts7/lib-diagnostics.test.js +40 -0
  664. package/dist/frontend/ts7/lib-diagnostics.test.js.map +1 -1
  665. package/dist/frontend/ts7/native-api.d.ts +1 -0
  666. package/dist/frontend/ts7/native-api.js +25 -2
  667. package/dist/frontend/ts7/native-api.js.map +1 -1
  668. package/dist/frontend/ts7/native-process.d.ts +9 -2
  669. package/dist/frontend/ts7/native-process.js +22 -4
  670. package/dist/frontend/ts7/native-process.js.map +1 -1
  671. package/dist/frontend/ts7/program-host.d.ts +11 -0
  672. package/dist/frontend/ts7/program-host.js +36 -22
  673. package/dist/frontend/ts7/program-host.js.map +1 -1
  674. package/dist/frontend/ts7/semantic-json.d.ts +9 -0
  675. package/dist/frontend/ts7/semantic-json.js +25 -5
  676. package/dist/frontend/ts7/semantic-json.js.map +1 -1
  677. package/dist/frontend/ts7/semantic-model.d.ts +3 -0
  678. package/dist/frontend/ts7/semantic-model.js +8 -1
  679. package/dist/frontend/ts7/semantic-model.js.map +1 -1
  680. package/dist/frontend/ts7/semantic-model.test.js +6 -1
  681. package/dist/frontend/ts7/semantic-model.test.js.map +1 -1
  682. package/dist/frontend/ts7/semantic-types.d.ts +1 -1
  683. package/dist/frontend/ts7/semantic-types.js +1 -1
  684. package/dist/frontend/ts7/semantic-types.js.map +1 -1
  685. package/dist/frontend/ts7/source-parser.js +3 -1
  686. package/dist/frontend/ts7/source-parser.js.map +1 -1
  687. package/dist/frontend/tsc-codes.js +10 -0
  688. package/dist/frontend/tsc-codes.js.map +1 -1
  689. package/dist/frontend/type-mapper.d.ts +18 -6
  690. package/dist/frontend/type-mapper.js +205 -44
  691. package/dist/frontend/type-mapper.js.map +1 -1
  692. package/dist/index.d.ts +44 -3
  693. package/dist/index.js +39 -8
  694. package/dist/index.js.map +1 -1
  695. package/dist/ir/builtin-effects.js +37 -0
  696. package/dist/ir/builtin-effects.js.map +1 -1
  697. package/dist/ir/builtin-signatures.d.ts +7 -2
  698. package/dist/ir/builtin-signatures.js +5104 -4894
  699. package/dist/ir/builtin-signatures.js.map +1 -1
  700. package/dist/ir/callback-specialization.d.ts +4 -2
  701. package/dist/ir/callback-specialization.js +24 -9
  702. package/dist/ir/callback-specialization.js.map +1 -1
  703. package/dist/ir/capture-values.js +4 -2
  704. package/dist/ir/capture-values.js.map +1 -1
  705. package/dist/ir/char-unit-locals.d.ts +12 -2
  706. package/dist/ir/char-unit-locals.js +400 -58
  707. package/dist/ir/char-unit-locals.js.map +1 -1
  708. package/dist/ir/char-unit-locals.test.js +111 -0
  709. package/dist/ir/char-unit-locals.test.js.map +1 -1
  710. package/dist/ir/constant-globals.js +18 -4
  711. package/dist/ir/constant-globals.js.map +1 -1
  712. package/dist/ir/expression-inlining.d.ts +15 -0
  713. package/dist/ir/expression-inlining.js +166 -0
  714. package/dist/ir/expression-inlining.js.map +1 -0
  715. package/dist/ir/expression-inlining.test.d.ts +1 -0
  716. package/dist/ir/expression-inlining.test.js +123 -0
  717. package/dist/ir/expression-inlining.test.js.map +1 -0
  718. package/dist/ir/function-references.js +2 -0
  719. package/dist/ir/function-references.js.map +1 -1
  720. package/dist/ir/function-references.test.js +6 -0
  721. package/dist/ir/function-references.test.js.map +1 -1
  722. package/dist/ir/int32-arrays.d.ts +27 -6
  723. package/dist/ir/int32-arrays.js +106 -18
  724. package/dist/ir/int32-arrays.js.map +1 -1
  725. package/dist/ir/int32-slots.d.ts +26 -1
  726. package/dist/ir/int32-slots.js +291 -5
  727. package/dist/ir/int32-slots.js.map +1 -1
  728. package/dist/ir/int32-slots.test.js +38 -0
  729. package/dist/ir/int32-slots.test.js.map +1 -1
  730. package/dist/ir/integer-loop-facts.d.ts +5 -0
  731. package/dist/ir/integer-loop-facts.js +90 -1
  732. package/dist/ir/integer-loop-facts.js.map +1 -1
  733. package/dist/ir/integer-loops.d.ts +14 -1
  734. package/dist/ir/integer-loops.js +107 -11
  735. package/dist/ir/integer-loops.js.map +1 -1
  736. package/dist/ir/integer-loops.test.js +70 -0
  737. package/dist/ir/integer-loops.test.js.map +1 -1
  738. package/dist/ir/integer-ranges.js +18 -2
  739. package/dist/ir/integer-ranges.js.map +1 -1
  740. package/dist/ir/integer-ranges.test.js +64 -4
  741. package/dist/ir/integer-ranges.test.js.map +1 -1
  742. package/dist/ir/ir.d.ts +63 -11
  743. package/dist/ir/ir.js +47 -7
  744. package/dist/ir/ir.js.map +1 -1
  745. package/dist/ir/ir.test.js +2 -1
  746. package/dist/ir/ir.test.js.map +1 -1
  747. package/dist/ir/js-ic.d.ts +10 -3
  748. package/dist/ir/js-ic.js +14 -2
  749. package/dist/ir/js-ic.js.map +1 -1
  750. package/dist/ir/js-ic.test.js +11 -0
  751. package/dist/ir/js-ic.test.js.map +1 -1
  752. package/dist/ir/node-index.d.ts +7 -0
  753. package/dist/ir/node-index.js +32 -0
  754. package/dist/ir/node-index.js.map +1 -1
  755. package/dist/ir/receiver-readers.d.ts +6 -1
  756. package/dist/ir/receiver-readers.js +53 -28
  757. package/dist/ir/receiver-readers.js.map +1 -1
  758. package/dist/ir/row-pairs.d.ts +15 -0
  759. package/dist/ir/row-pairs.js +373 -0
  760. package/dist/ir/row-pairs.js.map +1 -0
  761. package/dist/ir/row-pairs.test.d.ts +1 -0
  762. package/dist/ir/row-pairs.test.js +129 -0
  763. package/dist/ir/row-pairs.test.js.map +1 -0
  764. package/dist/ir/runtime-features.d.ts +17 -4
  765. package/dist/ir/runtime-features.js +94 -13
  766. package/dist/ir/runtime-features.js.map +1 -1
  767. package/dist/ir/scalar-records.d.ts +15 -0
  768. package/dist/ir/scalar-records.js +301 -1
  769. package/dist/ir/scalar-records.js.map +1 -1
  770. package/dist/ir/scalar-records.test.js +181 -1
  771. package/dist/ir/scalar-records.test.js.map +1 -1
  772. package/dist/ir/self-captures.js +8 -0
  773. package/dist/ir/self-captures.js.map +1 -1
  774. package/dist/ir/validate.js +78 -28
  775. package/dist/ir/validate.js.map +1 -1
  776. package/dist/library/fence-eval.js +4 -4
  777. package/dist/library/fence-eval.js.map +1 -1
  778. package/dist/library/ir-policy.js +5 -0
  779. package/dist/library/ir-policy.js.map +1 -1
  780. package/dist/library/library-cache.d.ts +1 -0
  781. package/dist/library/library-cache.js +1 -0
  782. package/dist/library/library-cache.js.map +1 -1
  783. package/dist/library/library-cache.test.js +13 -0
  784. package/dist/library/library-cache.test.js.map +1 -1
  785. package/dist/native/cache.d.ts +5 -1
  786. package/dist/native/cache.js +15 -3
  787. package/dist/native/cache.js.map +1 -1
  788. package/dist/native/cli.js +6 -0
  789. package/dist/native/cli.js.map +1 -1
  790. package/dist/native/compiler.d.ts +3 -0
  791. package/dist/native/compiler.js +72 -26
  792. package/dist/native/compiler.js.map +1 -1
  793. package/dist/native/compiler.test.js +87 -2
  794. package/dist/native/compiler.test.js.map +1 -1
  795. package/dist/native/executable-cache-open.test.d.ts +1 -0
  796. package/dist/native/executable-cache-open.test.js +80 -0
  797. package/dist/native/executable-cache-open.test.js.map +1 -0
  798. package/dist/native/executable-cache.d.ts +43 -3
  799. package/dist/native/executable-cache.js +177 -36
  800. package/dist/native/executable-cache.js.map +1 -1
  801. package/dist/native/executable-cache.test.js +103 -0
  802. package/dist/native/executable-cache.test.js.map +1 -1
  803. package/dist/native/prepare.d.ts +1 -1
  804. package/dist/native/prepare.js +49 -17
  805. package/dist/native/prepare.js.map +1 -1
  806. package/dist/native/prepare.test.js +69 -3
  807. package/dist/native/prepare.test.js.map +1 -1
  808. package/dist/native/sanitizer.d.ts +1 -1
  809. package/dist/native/sanitizer.js +17 -3
  810. package/dist/native/sanitizer.js.map +1 -1
  811. package/dist/native/sanitizer.test.js +4 -0
  812. package/dist/native/sanitizer.test.js.map +1 -1
  813. package/dist/node-islands/classify.d.ts +14 -0
  814. package/dist/node-islands/classify.js +114 -0
  815. package/dist/node-islands/classify.js.map +1 -0
  816. package/dist/node-islands/detect.d.ts +13 -0
  817. package/dist/node-islands/detect.js +805 -0
  818. package/dist/node-islands/detect.js.map +1 -0
  819. package/dist/node-islands/detect.test.d.ts +1 -0
  820. package/dist/node-islands/detect.test.js +136 -0
  821. package/dist/node-islands/detect.test.js.map +1 -0
  822. package/dist/node-islands/origin.d.ts +21 -0
  823. package/dist/node-islands/origin.js +60 -0
  824. package/dist/node-islands/origin.js.map +1 -0
  825. package/dist/node-islands/policy.d.ts +49 -0
  826. package/dist/node-islands/policy.js +130 -0
  827. package/dist/node-islands/policy.js.map +1 -0
  828. package/dist/node-islands/report.d.ts +22 -0
  829. package/dist/node-islands/report.js +326 -0
  830. package/dist/node-islands/report.js.map +1 -0
  831. package/dist/node-islands/report.test.d.ts +1 -0
  832. package/dist/node-islands/report.test.js +228 -0
  833. package/dist/node-islands/report.test.js.map +1 -0
  834. package/dist/node-islands/rules.d.ts +20 -0
  835. package/dist/node-islands/rules.js +91 -0
  836. package/dist/node-islands/rules.js.map +1 -0
  837. package/dist/node-islands/scan.d.ts +53 -0
  838. package/dist/node-islands/scan.js +104 -0
  839. package/dist/node-islands/scan.js.map +1 -0
  840. package/dist/node-islands/summary.d.ts +78 -0
  841. package/dist/node-islands/summary.js +26 -0
  842. package/dist/node-islands/summary.js.map +1 -0
  843. package/dist/project-config.d.ts +50 -0
  844. package/dist/project-config.js +372 -0
  845. package/dist/project-config.js.map +1 -0
  846. package/dist/project-config.test.d.ts +1 -0
  847. package/dist/project-config.test.js +154 -0
  848. package/dist/project-config.test.js.map +1 -0
  849. package/dist/wasm/discover.js +6 -31
  850. package/dist/wasm/discover.js.map +1 -1
  851. package/package.json +20 -20
  852. package/surface-manifest.json +21 -38
@@ -0,0 +1,3138 @@
1
+ /* Shape inference (results/design-shape-inference/DESIGN.md), stage S1:
2
+ * a whole-program allocation-site points-to analysis over the JavaScript of
3
+ * opted-in npm packages and the user files that call into them.
4
+ *
5
+ * Stage S1 is report-only: the analysis runs when SCRIPTC_DEBUG_SHAPES is
6
+ * set and prints its plan (report.ts). Nothing it computes reaches the
7
+ * lowering yet, so every program compiles exactly as before.
8
+ *
9
+ * The analysis (DESIGN.md §4):
10
+ * - Andersen-style inclusion constraints, solved with a worklist. Locals
11
+ * and parameters are one value node per binding (flow-insensitive in S1);
12
+ * heap fields are one node per (atom, name); arrays one element node.
13
+ * - Calls resolve by the callee's atoms: functions, class constructors,
14
+ * methods by the receiver's class chain (inherited members, getters and
15
+ * setters, `this.constructor`), closures stored in fields, `bind`, and
16
+ * builtin summaries for the common library surface.
17
+ * - Escape: an atom escapes when it reaches code the analysis cannot see
18
+ * (a ⊤ callee, a builtin without a summary, a store into a ⊤ object).
19
+ * Escaped functions run with ⊤ arguments; everything reachable from an
20
+ * escaped atom escapes.
21
+ * - Census: writes and reflection whose receiver may be ⊤ apply to every
22
+ * escaped atom (§5.4); the report uses them to decide which allocation
23
+ * sites could become native records (§5.5). */
24
+ import * as ts from "../ts7/adapter.js";
25
+ import { isJsSourceFile } from "../program.js";
26
+ import { npmStaticPackageOfPath } from "../npm-static.js";
27
+ import { AtomTable, MODELED_GLOBALS, STRING_METHOD_RESULTS } from "./domain.js";
28
+ /** Array.prototype members: other names on an array are own properties. */
29
+ const ARRAY_METHODS = new Set([
30
+ "at",
31
+ "concat",
32
+ "copyWithin",
33
+ "entries",
34
+ "every",
35
+ "fill",
36
+ "filter",
37
+ "find",
38
+ "findIndex",
39
+ "findLast",
40
+ "findLastIndex",
41
+ "flat",
42
+ "flatMap",
43
+ "forEach",
44
+ "includes",
45
+ "indexOf",
46
+ "join",
47
+ "keys",
48
+ "lastIndexOf",
49
+ "map",
50
+ "pop",
51
+ "push",
52
+ "reduce",
53
+ "reduceRight",
54
+ "reverse",
55
+ "shift",
56
+ "slice",
57
+ "some",
58
+ "sort",
59
+ "splice",
60
+ "toLocaleString",
61
+ "toReversed",
62
+ "toSorted",
63
+ "toSpliced",
64
+ "toString",
65
+ "unshift",
66
+ "values",
67
+ "with",
68
+ ]);
69
+ const MAX_STEPS = 20_000_000;
70
+ function list(arr) {
71
+ return arr?.nodes ?? [];
72
+ }
73
+ function isStatic(node) {
74
+ const mods = node.modifiers;
75
+ return list(mods).some((m) => m.kind === ts.SyntaxKind.StaticKeyword);
76
+ }
77
+ function unparen(node) {
78
+ let n = node;
79
+ for (;;) {
80
+ if (ts.isParenthesizedExpression(n))
81
+ n = n.expression;
82
+ else if (ts.isNonNullExpression(n))
83
+ n = n.expression;
84
+ else if (ts.isAsExpression(n) || ts.isSatisfiesExpression(n))
85
+ n = n.expression;
86
+ else
87
+ return n;
88
+ }
89
+ }
90
+ function propertyNameText(name) {
91
+ if (ts.isIdentifier(name) || ts.isPrivateIdentifier(name))
92
+ return name.text;
93
+ if (ts.isStringLiteral(name) || ts.isNoSubstitutionTemplateLiteral(name))
94
+ return name.text;
95
+ if (ts.isNumericLiteral(name))
96
+ return String(Number(name.text));
97
+ if (ts.isComputedPropertyName(name)) {
98
+ const e = unparen(name.expression);
99
+ if (ts.isStringLiteral(e) || ts.isNoSubstitutionTemplateLiteral(e))
100
+ return e.text;
101
+ if (ts.isNumericLiteral(e))
102
+ return String(Number(e.text));
103
+ }
104
+ return null;
105
+ }
106
+ function shortFile(fileName) {
107
+ const norm = fileName.split("\\").join("/");
108
+ const nm = norm.lastIndexOf("/node_modules/");
109
+ if (nm >= 0) {
110
+ const rest = norm.slice(nm + "/node_modules/".length).split("/");
111
+ const pkgLen = rest[0]?.startsWith("@") ? 2 : 1;
112
+ const pkg = rest.slice(0, pkgLen).join("/");
113
+ return `${pkg}/${rest[rest.length - 1]}`;
114
+ }
115
+ return norm.slice(norm.lastIndexOf("/") + 1);
116
+ }
117
+ export function locLabel(node) {
118
+ const sf = node.getSourceFile();
119
+ const { line } = ts.getLineAndCharacterOfPosition(sf, node.getStart(sf));
120
+ return `${shortFile(sf.fileName)}:${line + 1}`;
121
+ }
122
+ /** Whether a source file belongs to an opted-in package's JavaScript. */
123
+ export function isPackageJsFile(sf) {
124
+ return isJsSourceFile(sf) && npmStaticPackageOfPath(sf.fileName) !== null;
125
+ }
126
+ function isLoop(node) {
127
+ return (ts.isForStatement(node) ||
128
+ ts.isForOfStatement(node) ||
129
+ ts.isForInStatement(node) ||
130
+ ts.isWhileStatement(node) ||
131
+ ts.isDoStatement(node));
132
+ }
133
+ const LOOP_CALLBACK_METHODS = new Set([
134
+ "map",
135
+ "forEach",
136
+ "filter",
137
+ "some",
138
+ "every",
139
+ "find",
140
+ "findIndex",
141
+ "findLast",
142
+ "findLastIndex",
143
+ "reduce",
144
+ "reduceRight",
145
+ "flatMap",
146
+ "sort",
147
+ "toSorted",
148
+ "from",
149
+ "replace",
150
+ "replaceAll",
151
+ ]);
152
+ export function analyzeShapes(program, checker) {
153
+ return new Analyzer(program, checker).run();
154
+ }
155
+ class Analyzer {
156
+ program;
157
+ checker;
158
+ atoms = new AtomTable();
159
+ nodes = [];
160
+ functions = new Map();
161
+ sites = [];
162
+ siteAtoms = new Set();
163
+ ops = [];
164
+ calls = [];
165
+ escaped = new Map();
166
+ topWriteNames = new Map();
167
+ topComputedWrites = [];
168
+ fields = new Map();
169
+ elements = new Map();
170
+ top;
171
+ bindings = new Map();
172
+ exprMemo = new Map();
173
+ /** Current analysis context and the function whose clone it is. */
174
+ ctx = "";
175
+ ctxRoot = null;
176
+ classInfo = new Map();
177
+ boundCalls = new Set();
178
+ escapedFunctionCalls = new Set();
179
+ worklist = [];
180
+ steps = 0;
181
+ budgetExceeded = false;
182
+ currentFn = null;
183
+ loopDepth = 0;
184
+ files = [];
185
+ packageFiles = 0;
186
+ prims = new Map();
187
+ /** Per call site: the calling function and whether the site is in a loop
188
+ * (constraints fire during solving, after the walk has moved on). */
189
+ siteCtx = new Map();
190
+ forceLoop = false;
191
+ noteSite(site) {
192
+ if (!this.siteCtx.has(site))
193
+ this.siteCtx.set(site, { caller: this.currentFn, inLoop: this.loopDepth > 0 });
194
+ }
195
+ /** Builtin calls that invoke their callbacks once per value
196
+ * (JSON.parse revivers, JSON.stringify replacers and toJSON methods),
197
+ * which may run after the call's own handling. */
198
+ repeatingSites = new Set();
199
+ edgeFor(site, callee) {
200
+ const ctx = this.siteCtx.get(site);
201
+ this.calls.push({
202
+ caller: ctx?.caller ?? null,
203
+ callee,
204
+ inLoop: (ctx?.inLoop ?? false) || this.forceLoop || this.repeatingSites.has(site),
205
+ site,
206
+ });
207
+ }
208
+ constructor(program, checker) {
209
+ this.program = program;
210
+ this.checker = checker;
211
+ this.top = this.atoms.intern("top", () => ({ kind: "top", label: "⊤" }));
212
+ }
213
+ run() {
214
+ for (const sf of this.program.getImplementationSourceFiles()) {
215
+ const name = sf.fileName.split("\\").join("/");
216
+ const inPackage = isPackageJsFile(sf);
217
+ if (!inPackage && name.includes("/node_modules/"))
218
+ continue;
219
+ this.files.push(sf);
220
+ if (inPackage)
221
+ this.packageFiles++;
222
+ }
223
+ for (const sf of this.files)
224
+ this.checker.prefetchSourceFile(sf);
225
+ for (const sf of this.files)
226
+ this.moduleBody(sf);
227
+ this.finish();
228
+ return {
229
+ atoms: this.atoms,
230
+ nodes: this.nodes,
231
+ functions: this.functions,
232
+ sites: this.sites,
233
+ ops: this.ops,
234
+ calls: this.calls,
235
+ escaped: this.escaped,
236
+ topWriteNames: this.topWriteNames,
237
+ topComputedWrites: this.topComputedWrites,
238
+ fields: this.fields,
239
+ elements: this.elements,
240
+ top: this.top,
241
+ files: this.files,
242
+ packageFiles: this.packageFiles,
243
+ checker: this.checker,
244
+ budgetExceeded: this.budgetExceeded,
245
+ steps: this.steps,
246
+ topCause: this.topCause,
247
+ nodeLabel: this.nodeLabel,
248
+ escapedFunctions: this.escapedFunctionCalls,
249
+ protoOf: this.protoOf,
250
+ };
251
+ }
252
+ // ---- value nodes -------------------------------------------------------
253
+ newNode() {
254
+ const id = this.nodes.length;
255
+ this.nodes.push({ id, atoms: new Set(), succ: new Set(), onAtom: [], escapeSink: null });
256
+ return id;
257
+ }
258
+ /** Debugging (SCRIPTC_DEBUG_SHAPES_WHY): where each node's ⊤ came from. */
259
+ topCause = new Map();
260
+ nodeLabel = new Map();
261
+ cause = null;
262
+ traceTop = process.env["SCRIPTC_DEBUG_SHAPES_WHY"] !== undefined;
263
+ add(node, atom) {
264
+ const n = this.nodes[node];
265
+ if (n.atoms.has(atom))
266
+ return;
267
+ n.atoms.add(atom);
268
+ if (this.traceTop && atom === this.top && !this.topCause.has(node))
269
+ this.topCause.set(node, this.cause ??
270
+ (new Error().stack ?? "")
271
+ .split("\n")
272
+ .slice(2, 4)
273
+ .map((l) => l.trim())
274
+ .join(" < "));
275
+ this.worklist.push([node, atom]);
276
+ }
277
+ edge(from, to) {
278
+ if (from === to)
279
+ return;
280
+ const n = this.nodes[from];
281
+ if (n.succ.has(to))
282
+ return;
283
+ n.succ.add(to);
284
+ const saved = this.cause;
285
+ this.cause = from;
286
+ for (const a of n.atoms)
287
+ this.add(to, a);
288
+ this.cause = saved;
289
+ }
290
+ on(node, fn) {
291
+ const n = this.nodes[node];
292
+ n.onAtom.push(fn);
293
+ for (const a of [...n.atoms])
294
+ fn(a);
295
+ }
296
+ sink(node, reason) {
297
+ const n = this.nodes[node];
298
+ if (n.escapeSink !== null)
299
+ return;
300
+ n.escapeSink = reason;
301
+ for (const a of [...n.atoms])
302
+ this.escape(a, reason);
303
+ }
304
+ constNode(atom) {
305
+ const n = this.newNode();
306
+ this.add(n, atom);
307
+ return n;
308
+ }
309
+ prim(name) {
310
+ let a = this.prims.get(name);
311
+ if (a === undefined) {
312
+ a = this.atoms.intern(`prim:${name}`, () => ({ kind: "prim", label: name }));
313
+ this.prims.set(name, a);
314
+ }
315
+ return a;
316
+ }
317
+ /** ES5 constructor functions: the function's default prototype object,
318
+ * and which function each `new F()` instance atom belongs to. */
319
+ protoOf = new Map();
320
+ fnOfInstance = new Map();
321
+ protoAtom(fn) {
322
+ let p = this.protoOf.get(fn);
323
+ if (p === undefined) {
324
+ p = this.atoms.intern(`proto:${this.nodeKey(fn.node)}:${fn.ctx ?? ""}`, () => ({
325
+ kind: "object",
326
+ label: `${fn.label}.prototype`,
327
+ node: fn.node,
328
+ }));
329
+ this.protoOf.set(fn, p);
330
+ this.add(this.field(p, "constructor"), fn);
331
+ if (this.escaped.has(fn))
332
+ this.escape(p, `via ${fn.label}`);
333
+ }
334
+ return p;
335
+ }
336
+ builtin(path, receiver) {
337
+ const key = receiver === undefined ? `builtin:${path}` : `builtin:${path}@${receiver.id}`;
338
+ return this.atoms.intern(key, () => ({ kind: "builtin", label: path, path, receiver }));
339
+ }
340
+ solve() {
341
+ while (this.worklist.length > 0) {
342
+ if (++this.steps > MAX_STEPS) {
343
+ this.budgetExceeded = true;
344
+ return;
345
+ }
346
+ const [id, atom] = this.worklist.pop();
347
+ const n = this.nodes[id];
348
+ this.cause = id;
349
+ for (const s of n.succ)
350
+ this.add(s, atom);
351
+ this.cause = null;
352
+ for (const f of n.onAtom)
353
+ f(atom);
354
+ if (n.escapeSink !== null)
355
+ this.escape(atom, n.escapeSink);
356
+ }
357
+ }
358
+ // ---- heap ----------------------------------------------------------------
359
+ field(atom, name) {
360
+ let m = this.fields.get(atom);
361
+ if (m === undefined) {
362
+ m = new Map();
363
+ this.fields.set(atom, m);
364
+ }
365
+ let id = m.get(name);
366
+ if (id === undefined) {
367
+ id = this.newNode();
368
+ m.set(name, id);
369
+ if (this.traceTop)
370
+ this.nodeLabel.set(id, `${atom.label}.${name}`);
371
+ const byName = this.fieldReaders.get(atom);
372
+ const readers = byName?.get(name);
373
+ if (readers !== undefined) {
374
+ for (const dst of readers)
375
+ this.edge(id, dst);
376
+ byName.delete(name);
377
+ }
378
+ const reason = this.escaped.get(atom);
379
+ if (reason !== undefined) {
380
+ this.sink(id, reason);
381
+ if (this.topComputedWrites.length > 0 || this.topWriteNames.has(name))
382
+ this.add(id, this.top);
383
+ }
384
+ }
385
+ return id;
386
+ }
387
+ element(atom) {
388
+ let id = this.elements.get(atom);
389
+ if (id === undefined) {
390
+ id = this.newNode();
391
+ this.elements.set(atom, id);
392
+ const reason = this.escaped.get(atom);
393
+ if (reason !== undefined) {
394
+ this.sink(id, reason);
395
+ if (this.topComputedWrites.length > 0)
396
+ this.add(id, this.top);
397
+ }
398
+ }
399
+ return id;
400
+ }
401
+ escape(atom, reason) {
402
+ if (atom.kind === "prim" || atom.kind === "top")
403
+ return;
404
+ if (atom.kind === "builtin" && atom.receiver === undefined)
405
+ return;
406
+ if (this.escaped.has(atom))
407
+ return;
408
+ this.escaped.set(atom, reason);
409
+ const via = `via ${atom.label}`;
410
+ // Unknown code reaches a constructor's prototype through the function
411
+ // and through its instances.
412
+ const ctor = atom.kind === "function" ? atom : this.fnOfInstance.get(atom);
413
+ if (ctor !== undefined && ctor.node !== undefined && (atom !== ctor || this.protoOf.has(ctor)))
414
+ this.escape(this.protoAtom(ctor), via);
415
+ const fm = this.fields.get(atom);
416
+ if (fm !== undefined) {
417
+ for (const [name, id] of fm) {
418
+ this.sink(id, via);
419
+ if (this.topComputedWrites.length > 0 || this.topWriteNames.has(name))
420
+ this.add(id, this.top);
421
+ }
422
+ }
423
+ const el = this.elements.get(atom);
424
+ if (el !== undefined) {
425
+ this.sink(el, via);
426
+ if (this.topComputedWrites.length > 0)
427
+ this.add(el, this.top);
428
+ }
429
+ if (atom.receiver !== undefined)
430
+ this.escape(atom.receiver, via);
431
+ if (atom.kind === "function") {
432
+ const info = this.infoOfAtom(atom);
433
+ if (info !== undefined)
434
+ this.escapeFunction(info, via);
435
+ }
436
+ if ((atom.kind === "instance" || atom.kind === "class") && atom.node !== undefined) {
437
+ // Unknown code may call any member with any arguments.
438
+ for (const member of this.classMembers(atom.node, atom.kind === "class")) {
439
+ const info = this.functionInfo(member, this.ownerOf(member), this.receiverCtx(atom));
440
+ this.add(info.thisNode, atom);
441
+ this.escapeFunction(info, via);
442
+ }
443
+ }
444
+ if (atom.kind === "promise")
445
+ this.sink(this.field(atom, "value"), via);
446
+ }
447
+ /** A function unknown code may call: ⊤ arguments and receiver; its
448
+ * results escape. */
449
+ escapeFunction(info, reason) {
450
+ if (this.escapedFunctionCalls.has(info))
451
+ return;
452
+ this.escapedFunctionCalls.add(info);
453
+ this.activate(info);
454
+ for (const p of info.params)
455
+ this.add(p, this.top);
456
+ if (!info.isArrow && info.ownerClass === null)
457
+ this.add(info.thisNode, this.top);
458
+ this.sink(info.ret, reason);
459
+ }
460
+ /** Property names that untyped code writes on receivers that may be ⊤ (census). */
461
+ noteTopWrite(name, node) {
462
+ if (name === null) {
463
+ const first = this.topComputedWrites.length === 0;
464
+ this.topComputedWrites.push(node);
465
+ if (first) {
466
+ for (const atom of [...this.escaped.keys()]) {
467
+ for (const id of (this.fields.get(atom) ?? new Map()).values())
468
+ this.add(id, this.top);
469
+ const el = this.elements.get(atom);
470
+ if (el !== undefined)
471
+ this.add(el, this.top);
472
+ }
473
+ }
474
+ return;
475
+ }
476
+ if (this.topWriteNames.has(name))
477
+ return;
478
+ this.topWriteNames.set(name, node);
479
+ for (const atom of [...this.escaped.keys()]) {
480
+ const id = this.fields.get(atom)?.get(name);
481
+ if (id !== undefined)
482
+ this.add(id, this.top);
483
+ }
484
+ }
485
+ // ---- classes ---------------------------------------------------------------
486
+ /** The base class declaration of `decl`, via the checker; null at a
487
+ * builtin base or none; undefined when unresolved. */
488
+ baseClass(decl) {
489
+ const heritage = list(decl.heritageClauses).find((c) => c.token === ts.SyntaxKind.ExtendsKeyword)?.types?.nodes[0];
490
+ if (heritage === undefined)
491
+ return null;
492
+ const e = unparen(heritage.expression);
493
+ if (!ts.isIdentifier(e) && !ts.isPropertyAccessExpression(e))
494
+ return undefined;
495
+ let d = this.resolve(ts.isIdentifier(e) ? e : e.name);
496
+ // `var C = class C { … }` (bundler output)
497
+ if (d !== undefined &&
498
+ ts.isVariableDeclaration(d) &&
499
+ d.initializer !== undefined &&
500
+ ts.isClassExpression(unparen(d.initializer)))
501
+ d = unparen(d.initializer);
502
+ if (d !== undefined && ts.isClassLikeDeclaration(d))
503
+ return d;
504
+ if (d !== undefined && d.getSourceFile().isDeclarationFile)
505
+ return null;
506
+ return undefined;
507
+ }
508
+ classChain(decl) {
509
+ const out = [];
510
+ let cur = decl;
511
+ while (cur && out.length < 64 && !out.includes(cur)) {
512
+ out.push(cur);
513
+ cur = this.baseClass(cur);
514
+ }
515
+ return out;
516
+ }
517
+ /** Method, accessor and constructor declarations of a class chain. */
518
+ classMembers(decl, statics) {
519
+ const out = [];
520
+ for (const c of this.classChain(decl)) {
521
+ for (const m of list(c.members)) {
522
+ if (isStatic(m) !== statics)
523
+ continue;
524
+ if (ts.isMethodDeclaration(m) ||
525
+ ts.isGetAccessorDeclaration(m) ||
526
+ ts.isSetAccessorDeclaration(m))
527
+ out.push(m);
528
+ else if (ts.isPropertyDeclaration(m) && m.initializer !== undefined) {
529
+ const init = unparen(m.initializer);
530
+ if (ts.isArrowFunction(init) || ts.isFunctionExpression(init))
531
+ out.push(init);
532
+ }
533
+ }
534
+ }
535
+ return out;
536
+ }
537
+ lookupMember(decl, name, statics) {
538
+ for (const c of this.classChain(decl)) {
539
+ let get;
540
+ let set;
541
+ for (const m of list(c.members)) {
542
+ if (isStatic(m) !== statics)
543
+ continue;
544
+ const mn = m.name;
545
+ if (mn === undefined || propertyNameText(mn) !== name)
546
+ continue;
547
+ if (ts.isMethodDeclaration(m))
548
+ return { kind: "method", method: m };
549
+ if (ts.isGetAccessorDeclaration(m))
550
+ get = m;
551
+ if (ts.isSetAccessorDeclaration(m))
552
+ set = m;
553
+ if (ts.isPropertyDeclaration(m))
554
+ return null; // an own field: data
555
+ }
556
+ if (get || set)
557
+ return {
558
+ kind: get && set ? "both" : get ? "getter" : "setter",
559
+ ...(get ? { get } : {}),
560
+ ...(set ? { set } : {}),
561
+ };
562
+ }
563
+ return null;
564
+ }
565
+ // ---- symbols -----------------------------------------------------------------
566
+ resolve(id) {
567
+ let sym = this.checker.getSymbolAtLocation(id);
568
+ if (sym === undefined)
569
+ return undefined;
570
+ if (sym.flags & ts.SymbolFlags.Alias) {
571
+ try {
572
+ sym = this.checker.getAliasedSymbol(sym);
573
+ }
574
+ catch {
575
+ return undefined;
576
+ }
577
+ }
578
+ return sym.valueDeclaration ?? sym.declarations[0];
579
+ }
580
+ binding(decl) {
581
+ const key = this.ctxKey(decl);
582
+ let id = this.bindings.get(key);
583
+ if (id === undefined) {
584
+ id = this.newNode();
585
+ this.bindings.set(key, id);
586
+ if (this.traceTop)
587
+ this.nodeLabel.set(id, `binding ${decl.name?.text ?? "?"}@${locLabel(decl)}${this.ctx !== "" ? ` [${this.ctx}]` : ""}`);
588
+ }
589
+ return id;
590
+ }
591
+ /** Bindings and expressions inside the function being cloned belong to
592
+ * the clone's context; everything else to the default context. */
593
+ ctxKey(node) {
594
+ const root = this.ctxRoot;
595
+ const inside = root !== null &&
596
+ node.getSourceFile() === root.getSourceFile() &&
597
+ node.pos >= root.pos &&
598
+ node.end <= root.end;
599
+ return `${inside ? this.ctx : ""}|${this.nodeKey(node)}`;
600
+ }
601
+ receiverCtx(atom) {
602
+ return atom.kind === "instance" || atom.kind === "class" ? `C${atom.id}` : "";
603
+ }
604
+ infoOfAtom(atom) {
605
+ if (atom.node === undefined)
606
+ return undefined;
607
+ return this.functions.get(`${atom.ctx ?? ""}|${this.nodeKey(atom.node)}`);
608
+ }
609
+ // ---- functions ---------------------------------------------------------------
610
+ functionInfo(node, ownerClass, ctxArg = "") {
611
+ // A nested closure walked inside a clone shares the clone's context.
612
+ const inherit = ctxArg === "" &&
613
+ this.ctxRoot !== null &&
614
+ node.getSourceFile() === this.ctxRoot.getSourceFile() &&
615
+ node.pos >= this.ctxRoot.pos &&
616
+ node.end <= this.ctxRoot.end;
617
+ const ctx = ctxArg !== "" ? ctxArg : inherit ? this.ctx : "";
618
+ const root = ctxArg !== "" ? node : inherit ? this.ctxRoot : null;
619
+ const fkey = `${ctx}|${this.nodeKey(node)}`;
620
+ const existing = this.functions.get(fkey);
621
+ if (existing !== undefined)
622
+ return existing;
623
+ const savedCtx = this.ctx;
624
+ const savedRoot = this.ctxRoot;
625
+ this.ctx = ctx;
626
+ this.ctxRoot = root;
627
+ const fn = node;
628
+ const isArrow = ts.isArrowFunction(node);
629
+ const params = [];
630
+ let rest = -1;
631
+ for (const p of list(fn.parameters)) {
632
+ const id = this.binding(p);
633
+ if (p.dotDotDotToken !== undefined)
634
+ rest = params.length;
635
+ params.push(id);
636
+ }
637
+ const mods = list(fn.modifiers);
638
+ const sf = node.getSourceFile();
639
+ const nameNode = fn.name;
640
+ const name = nameNode !== undefined ? (propertyNameText(nameNode) ?? "<computed>") : null;
641
+ const owner = ownerClass !== null ? this.className(ownerClass) : null;
642
+ const label = `${owner !== null ? `${owner}.` : ""}${name ?? (ts.isConstructorDeclaration(node) ? "constructor" : "<fn>")}@${locLabel(node)}`;
643
+ const info = {
644
+ node,
645
+ ctx,
646
+ root,
647
+ walked: false,
648
+ label: ctx === "" ? label : `${label} [${this.ctxLabel(ctx)}]`,
649
+ params,
650
+ rest,
651
+ thisNode: isArrow && this.currentFn !== null ? this.currentFn.thisNode : this.newNode(),
652
+ ret: this.newNode(),
653
+ isArrow,
654
+ isAsync: mods.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword),
655
+ isGenerator: fn.asteriskToken !== undefined,
656
+ usesArguments: false,
657
+ argPos: null,
658
+ ownerClass,
659
+ inPackage: isPackageJsFile(sf),
660
+ };
661
+ this.functions.set(fkey, info);
662
+ this.ctx = savedCtx;
663
+ this.ctxRoot = savedRoot;
664
+ return info;
665
+ }
666
+ /** Walks a function's body the first time it can run. */
667
+ activate(info) {
668
+ if (info.walked)
669
+ return;
670
+ info.walked = true;
671
+ if (ts.isSourceFile(info.node) || ts.isClassLikeDeclaration(info.node))
672
+ return;
673
+ const fn = info.node;
674
+ const savedCtx = this.ctx;
675
+ const savedRoot = this.ctxRoot;
676
+ const saved = this.currentFn;
677
+ const savedLoop = this.loopDepth;
678
+ this.ctx = info.ctx;
679
+ this.ctxRoot = info.root;
680
+ this.currentFn = info;
681
+ this.loopDepth = 0;
682
+ for (const p of list(fn.parameters)) {
683
+ if (p.initializer !== undefined)
684
+ this.edge(this.expr(p.initializer), this.binding(p));
685
+ if (p.dotDotDotToken !== undefined) {
686
+ const arr = this.atoms.intern(`rest:${this.nodes.length}`, () => ({
687
+ kind: "array",
688
+ label: `rest@${locLabel(p)}`,
689
+ node: p,
690
+ }));
691
+ this.add(this.binding(p), arr);
692
+ }
693
+ this.bindPattern(p.name, this.binding(p));
694
+ }
695
+ const body = fn.body;
696
+ if (body !== undefined) {
697
+ if (ts.isBlock(body))
698
+ this.stmts(list(body.statements));
699
+ else
700
+ this.edge(this.expr(body), info.ret);
701
+ }
702
+ this.currentFn = saved;
703
+ this.loopDepth = savedLoop;
704
+ this.ctx = savedCtx;
705
+ this.ctxRoot = savedRoot;
706
+ if (info.usesArguments) {
707
+ for (const p of info.params)
708
+ this.add(p, this.top);
709
+ }
710
+ }
711
+ /** The atom of a function node (memoized by its info). */
712
+ fnAtom(node, ownerClass, ctx = "") {
713
+ const info = this.functionInfo(node, ownerClass, ctx);
714
+ return this.atoms.intern(`fn:${info.ret}`, () => ({
715
+ kind: "function",
716
+ label: info.label,
717
+ node,
718
+ ctx: info.ctx,
719
+ }));
720
+ }
721
+ ctxLabel(ctx) {
722
+ if (ctx.startsWith("C"))
723
+ return `this=${this.atoms.atoms[Number(ctx.slice(1))]?.label ?? ctx}`;
724
+ return ctx;
725
+ }
726
+ className(decl) {
727
+ const own = decl.name?.text;
728
+ if (own !== undefined)
729
+ return own;
730
+ const p = decl.parent;
731
+ if (p !== undefined && ts.isVariableDeclaration(p) && ts.isIdentifier(p.name))
732
+ return p.name.text;
733
+ return `<class@${locLabel(decl)}>`;
734
+ }
735
+ classAtoms(decl) {
736
+ const name = this.className(decl);
737
+ const cls = this.atoms.intern(`class:${this.nodeKey(decl)}`, () => ({
738
+ kind: "class",
739
+ label: `class ${name}`,
740
+ node: decl,
741
+ }));
742
+ const inst = this.atoms.intern(`inst:${this.nodeKey(decl)}`, () => ({
743
+ kind: "instance",
744
+ label: name,
745
+ node: decl,
746
+ }));
747
+ this.ensureClass(decl);
748
+ return { cls, inst };
749
+ }
750
+ nodeKeys = new Map();
751
+ nodeKey(node) {
752
+ let k = this.nodeKeys.get(node);
753
+ if (k === undefined) {
754
+ k = this.nodeKeys.size;
755
+ this.nodeKeys.set(node, k);
756
+ }
757
+ return k;
758
+ }
759
+ /** Registers a class: member functions, field initializers (as a pseudo
760
+ * function run at construction) and static initializers. */
761
+ ensureClass(decl) {
762
+ const existing = this.classInfo.get(decl);
763
+ if (existing !== undefined)
764
+ return existing;
765
+ const c = decl;
766
+ const label = this.className(decl);
767
+ const mk = (suffix) => ({
768
+ node: decl,
769
+ ctx: "",
770
+ root: null,
771
+ walked: true,
772
+ label: `${label}.${suffix}@${locLabel(decl)}`,
773
+ params: [],
774
+ rest: -1,
775
+ thisNode: this.newNode(),
776
+ ret: this.newNode(),
777
+ isArrow: false,
778
+ isAsync: false,
779
+ isGenerator: false,
780
+ usesArguments: false,
781
+ argPos: null,
782
+ ownerClass: decl,
783
+ inPackage: isPackageJsFile(decl.getSourceFile()),
784
+ });
785
+ const entry = { initFn: mk("<fields>"), staticInit: mk("<static>") };
786
+ this.classInfo.set(decl, entry);
787
+ const cls = this.atoms.intern(`class:${this.nodeKey(decl)}`, () => ({
788
+ kind: "class",
789
+ label: `class ${label}`,
790
+ node: decl,
791
+ }));
792
+ this.add(entry.staticInit.thisNode, cls);
793
+ const saved = this.currentFn;
794
+ for (const m of list(c.members)) {
795
+ const statics = isStatic(m);
796
+ if (ts.isMethodDeclaration(m) ||
797
+ ts.isGetAccessorDeclaration(m) ||
798
+ ts.isSetAccessorDeclaration(m) ||
799
+ ts.isConstructorDeclaration(m)) {
800
+ continue;
801
+ }
802
+ if (ts.isPropertyDeclaration(m)) {
803
+ const name = propertyNameText(m.name);
804
+ const init = statics ? entry.staticInit : entry.initFn;
805
+ this.currentFn = init;
806
+ const value = m.initializer !== undefined
807
+ ? this.exprIn(m.initializer, decl)
808
+ : this.constNode(this.prim("undefined"));
809
+ if (name !== null)
810
+ this.storeConstraint(init.thisNode, name, value, m);
811
+ continue;
812
+ }
813
+ if (ts.isClassStaticBlockDeclaration(m)) {
814
+ this.currentFn = entry.staticInit;
815
+ this.stmts(list(m.body.statements));
816
+ }
817
+ }
818
+ this.currentFn = saved;
819
+ return entry;
820
+ }
821
+ /** An initializer expression: arrow functions in field initializers take
822
+ * the instance as `this` and belong to the class. */
823
+ exprIn(e, ownerClass) {
824
+ const u = unparen(e);
825
+ if (ts.isArrowFunction(u) || ts.isFunctionExpression(u)) {
826
+ const n = this.newNode();
827
+ this.add(n, this.fnAtom(u, ts.isArrowFunction(u) ? null : ownerClass));
828
+ return n;
829
+ }
830
+ return this.expr(e);
831
+ }
832
+ /** `new C(args)` on a class atom: the instance, the field initializers of
833
+ * every class in the chain, and the constructor (or the implicit one). */
834
+ construct(decl, args, spread, dst, site, inst) {
835
+ const atoms = this.classAtoms(decl);
836
+ const instance = inst ?? atoms.inst;
837
+ this.add(dst, instance);
838
+ this.callConstructorChain(decl, instance, args, spread, site);
839
+ }
840
+ callConstructorChain(decl, instance, args, spread, site) {
841
+ const key = `ctor:${this.nodeKey(decl)}:${instance.id}:${this.nodeKey(site)}`;
842
+ if (this.boundCalls.has(key))
843
+ return;
844
+ this.boundCalls.add(key);
845
+ const entry = this.ensureClass(decl);
846
+ this.add(entry.initFn.thisNode, instance);
847
+ const ctor = list(decl.members).find((m) => ts.isConstructorDeclaration(m));
848
+ if (ctor !== undefined) {
849
+ const info = this.functionInfo(ctor, decl, this.receiverCtx(instance));
850
+ this.activate(info);
851
+ this.add(info.thisNode, instance);
852
+ this.bindArgs(info, args, spread);
853
+ this.edgeFor(site, info);
854
+ return;
855
+ }
856
+ const base = this.baseClass(decl);
857
+ if (base)
858
+ this.callConstructorChain(base, instance, args, spread, site);
859
+ }
860
+ bindArgs(info, args, spread) {
861
+ if (info.argPos !== null) {
862
+ for (let i = 0; i < info.argPos.length; i++) {
863
+ if (spread || i >= info.argPos.length - 1) {
864
+ for (const a of args.slice(i))
865
+ this.edge(a, info.argPos[i]);
866
+ if (spread)
867
+ this.add(info.argPos[i], this.top);
868
+ }
869
+ else if (i < args.length)
870
+ this.edge(args[i], info.argPos[i]);
871
+ else
872
+ this.add(info.argPos[i], this.prim("undefined"));
873
+ }
874
+ }
875
+ if (spread) {
876
+ for (const p of info.params)
877
+ this.add(p, this.top);
878
+ for (const a of args)
879
+ this.sink(a, `spread into ${info.label}`);
880
+ return;
881
+ }
882
+ for (let i = 0; i < info.params.length; i++) {
883
+ if (i === info.rest) {
884
+ const restAtoms = [...this.nodes[info.params[i]].atoms];
885
+ for (const ra of restAtoms)
886
+ for (let j = i; j < args.length; j++)
887
+ this.edge(args[j], this.element(ra));
888
+ break;
889
+ }
890
+ if (i < args.length)
891
+ this.edge(args[i], info.params[i]);
892
+ else
893
+ this.add(info.params[i], this.prim("undefined"));
894
+ }
895
+ }
896
+ /** Call of a function atom with a receiver node. */
897
+ callFunction(info, thisNode, args, spread, dst, site) {
898
+ // `() => Object.create(null)` helpers: each call site gets its own
899
+ // dictionary, as if the helper were inlined.
900
+ if (this.isFactory(info.node)) {
901
+ const d = this.atoms.intern(`dict:${this.nodeKey(site)}`, () => ({
902
+ kind: "dictionary",
903
+ label: `Object.create@${locLabel(site)}`,
904
+ node: site,
905
+ }));
906
+ this.add(dst, d);
907
+ return;
908
+ }
909
+ this.activate(info);
910
+ const fnNode = info.node;
911
+ const key = `call:${info.ctx}|${this.nodeKey(fnNode)}:${this.nodeKey(site)}:${thisNode ?? -1}:${dst}`;
912
+ if (this.boundCalls.has(key))
913
+ return;
914
+ this.boundCalls.add(key);
915
+ if (thisNode !== null && !info.isArrow)
916
+ this.edge(thisNode, info.thisNode);
917
+ this.bindArgs(info, args, spread);
918
+ if (info.isAsync) {
919
+ const p = this.promiseAtom(fnNode, `async ${info.label}`);
920
+ this.awaitInto(info.ret, this.field(p, "value"));
921
+ this.add(dst, p);
922
+ }
923
+ else if (info.isGenerator) {
924
+ this.add(dst, this.top);
925
+ }
926
+ else
927
+ this.edge(info.ret, dst);
928
+ this.edgeFor(site, info);
929
+ }
930
+ factories = new Map();
931
+ isFactory(node) {
932
+ let r = this.factories.get(node);
933
+ if (r === undefined) {
934
+ r = false;
935
+ const fn = node;
936
+ let e = fn.body;
937
+ if (e !== undefined && ts.isBlock(e)) {
938
+ const st = e.statements.nodes;
939
+ e = st.length === 1 && ts.isReturnStatement(st[0]) ? st[0].expression : undefined;
940
+ }
941
+ if (e !== undefined && !ts.isSourceFile(node)) {
942
+ const u = unparen(e);
943
+ r =
944
+ ts.isCallExpression(u) &&
945
+ u.expression.getText() === "Object.create" &&
946
+ u.arguments.nodes.length === 1 &&
947
+ u.arguments.nodes[0].kind === ts.SyntaxKind.NullKeyword;
948
+ }
949
+ this.factories.set(node, r);
950
+ }
951
+ return r;
952
+ }
953
+ promiseAtom(site, label) {
954
+ return this.atoms.intern(`promise:${this.nodeKey(site)}`, () => ({
955
+ kind: "promise",
956
+ label: `Promise@${label}`,
957
+ node: site,
958
+ }));
959
+ }
960
+ /** dst ⊇ awaited(src). */
961
+ awaitInto(src, dst) {
962
+ this.on(src, (a) => {
963
+ if (a.kind === "promise")
964
+ this.edge(this.field(a, "value"), dst);
965
+ else
966
+ this.add(dst, a);
967
+ });
968
+ }
969
+ syntheticArray(site, tag) {
970
+ return this.atoms.intern(`arr:${tag}:${this.nodeKey(site)}`, () => ({
971
+ kind: "array",
972
+ label: `${tag}[]@${locLabel(site)}`,
973
+ node: site,
974
+ }));
975
+ }
976
+ // ---- statements ----------------------------------------------------------------
977
+ moduleBody(sf) {
978
+ const info = {
979
+ node: sf,
980
+ ctx: "",
981
+ root: null,
982
+ walked: true,
983
+ label: `<module ${shortFile(sf.fileName)}>`,
984
+ params: [],
985
+ rest: -1,
986
+ thisNode: this.constNode(this.prim("undefined")),
987
+ ret: this.newNode(),
988
+ isArrow: false,
989
+ isAsync: false,
990
+ isGenerator: false,
991
+ usesArguments: false,
992
+ argPos: null,
993
+ ownerClass: null,
994
+ inPackage: isPackageJsFile(sf),
995
+ };
996
+ this.functions.set(`|${this.nodeKey(sf)}`, info);
997
+ this.currentFn = info;
998
+ this.stmts(list(sf.statements));
999
+ this.currentFn = null;
1000
+ }
1001
+ stmts(stmts) {
1002
+ for (const s of stmts)
1003
+ this.stmt(s);
1004
+ }
1005
+ stmt(s) {
1006
+ if (ts.isVariableStatement(s)) {
1007
+ for (const d of list(s.declarationList.declarations))
1008
+ this.varDecl(d);
1009
+ return;
1010
+ }
1011
+ if (ts.isExpressionStatement(s)) {
1012
+ this.expr(s.expression);
1013
+ return;
1014
+ }
1015
+ if (ts.isReturnStatement(s)) {
1016
+ if (s.expression !== undefined && this.currentFn !== null)
1017
+ this.edge(this.expr(s.expression), this.currentFn.ret);
1018
+ return;
1019
+ }
1020
+ if (ts.isFunctionDeclaration(s)) {
1021
+ const b = this.binding(s);
1022
+ const saved = this.currentFn;
1023
+ this.currentFn = null;
1024
+ this.add(b, this.fnAtom(s, null));
1025
+ this.currentFn = saved;
1026
+ return;
1027
+ }
1028
+ if (ts.isClassDeclaration(s)) {
1029
+ const b = this.binding(s);
1030
+ this.add(b, this.classAtoms(s).cls);
1031
+ return;
1032
+ }
1033
+ if (isLoop(s)) {
1034
+ if (ts.isForOfStatement(s) || ts.isForInStatement(s)) {
1035
+ const src = this.expr(s.expression);
1036
+ const target = this.newNode();
1037
+ if (ts.isForInStatement(s))
1038
+ this.add(target, this.prim("string"));
1039
+ else
1040
+ this.iterateInto(src, target, s);
1041
+ const init = s.initializer;
1042
+ if (ts.isVariableDeclarationList(init)) {
1043
+ for (const d of list(init.declarations)) {
1044
+ this.edge(target, this.binding(d));
1045
+ this.bindPattern(d.name, this.binding(d));
1046
+ }
1047
+ }
1048
+ else
1049
+ this.assignTo(init, target);
1050
+ }
1051
+ this.loopDepth++;
1052
+ if (ts.isForStatement(s)) {
1053
+ if (s.initializer !== undefined) {
1054
+ if (ts.isVariableDeclarationList(s.initializer))
1055
+ for (const d of list(s.initializer.declarations))
1056
+ this.varDecl(d);
1057
+ else
1058
+ this.expr(s.initializer);
1059
+ }
1060
+ if (s.condition !== undefined)
1061
+ this.expr(s.condition);
1062
+ if (s.incrementor !== undefined)
1063
+ this.expr(s.incrementor);
1064
+ }
1065
+ if (ts.isWhileStatement(s) || ts.isDoStatement(s))
1066
+ this.expr(s.expression);
1067
+ const body = s.statement;
1068
+ if (body !== undefined)
1069
+ this.stmt(body);
1070
+ this.loopDepth--;
1071
+ return;
1072
+ }
1073
+ if (ts.isTryStatement(s)) {
1074
+ this.stmts(list(s.tryBlock.statements));
1075
+ if (s.catchClause !== undefined) {
1076
+ const v = s.catchClause.variableDeclaration;
1077
+ if (v !== undefined) {
1078
+ this.add(this.binding(v), this.top);
1079
+ this.bindPattern(v.name, this.binding(v));
1080
+ }
1081
+ this.stmts(list(s.catchClause.block.statements));
1082
+ }
1083
+ if (s.finallyBlock !== undefined)
1084
+ this.stmts(list(s.finallyBlock.statements));
1085
+ return;
1086
+ }
1087
+ if (ts.isThrowStatement(s)) {
1088
+ this.sink(this.expr(s.expression), `thrown at ${locLabel(s)}`);
1089
+ return;
1090
+ }
1091
+ if (ts.isImportDeclaration(s) ||
1092
+ ts.isExportDeclaration(s) ||
1093
+ ts.isInterfaceDeclaration(s) ||
1094
+ ts.isTypeAliasDeclaration(s))
1095
+ return;
1096
+ if (ts.isExportAssignment(s)) {
1097
+ this.expr(s.expression);
1098
+ return;
1099
+ }
1100
+ // Blocks, ifs, switches, labels: walk children, evaluating expressions.
1101
+ ts.forEachChild(s, (child) => {
1102
+ if (ts.isExpression(child))
1103
+ this.expr(child);
1104
+ else
1105
+ this.stmt(child);
1106
+ return undefined;
1107
+ });
1108
+ }
1109
+ varDecl(d) {
1110
+ const b = this.binding(d);
1111
+ if (d.initializer !== undefined)
1112
+ this.edge(this.expr(d.initializer), b);
1113
+ this.bindPattern(d.name, b);
1114
+ }
1115
+ /** Destructuring: binding elements read from the source node. */
1116
+ bindPattern(name, src) {
1117
+ if (ts.isIdentifier(name))
1118
+ return;
1119
+ if (ts.isObjectBindingPattern(name)) {
1120
+ for (const el of list(name.elements)) {
1121
+ const b = this.binding(el);
1122
+ if (el.dotDotDotToken !== undefined) {
1123
+ this.add(b, this.top);
1124
+ continue;
1125
+ }
1126
+ const keyNode = el.propertyName ?? el.name;
1127
+ const key = keyNode !== undefined ? propertyNameText(keyNode) : null;
1128
+ if (key !== null)
1129
+ this.loadConstraint(src, key, b, el);
1130
+ else
1131
+ this.add(b, this.top);
1132
+ if (el.initializer !== undefined)
1133
+ this.edge(this.expr(el.initializer), b);
1134
+ if (el.name !== undefined)
1135
+ this.bindPattern(el.name, b);
1136
+ }
1137
+ return;
1138
+ }
1139
+ if (ts.isArrayBindingPattern(name)) {
1140
+ let i = 0;
1141
+ for (const el of list(name.elements)) {
1142
+ if (ts.isBindingElement(el)) {
1143
+ const b = this.binding(el);
1144
+ if (el.dotDotDotToken !== undefined)
1145
+ this.add(b, this.top);
1146
+ else
1147
+ this.iterateInto(src, b, el, i);
1148
+ if (el.initializer !== undefined)
1149
+ this.edge(this.expr(el.initializer), b);
1150
+ if (el.name !== undefined)
1151
+ this.bindPattern(el.name, b);
1152
+ }
1153
+ i++;
1154
+ }
1155
+ }
1156
+ }
1157
+ /** Element values of an iterable. */
1158
+ iterateInto(src, dst, site, _index) {
1159
+ this.on(src, (a) => {
1160
+ if (a.kind === "array" || a.kind === "collection")
1161
+ this.edge(this.element(a), dst);
1162
+ else if (a.kind === "prim" && a.label === "string")
1163
+ this.add(dst, this.prim("string"));
1164
+ else if (a.kind === "prim" || a.kind === "object" || a.kind === "dictionary") {
1165
+ /* not iterable (a TypeError): no value. Literals with a
1166
+ Symbol.iterator member have a computed key; they are G sites. */
1167
+ }
1168
+ else {
1169
+ this.add(dst, this.top);
1170
+ if (a.kind !== "top")
1171
+ this.escape(a, `iterated at ${locLabel(site)}`);
1172
+ }
1173
+ });
1174
+ }
1175
+ // ---- expressions ---------------------------------------------------------------
1176
+ expr(e) {
1177
+ const key = this.ctxKey(e);
1178
+ const memo = this.exprMemo.get(key);
1179
+ if (memo !== undefined)
1180
+ return memo;
1181
+ const id = this.exprUncached(e);
1182
+ this.exprMemo.set(key, id);
1183
+ if (this.traceTop && !this.nodeLabel.has(id))
1184
+ this.nodeLabel.set(id, `expr ${e.getText().slice(0, 40).replace(/\s+/g, " ")}@${locLabel(e)}`);
1185
+ return id;
1186
+ }
1187
+ exprUncached(e) {
1188
+ const u = unparen(e);
1189
+ if (u !== e)
1190
+ return this.expr(u);
1191
+ switch (e.kind) {
1192
+ case ts.SyntaxKind.StringLiteral:
1193
+ case ts.SyntaxKind.NoSubstitutionTemplateLiteral:
1194
+ case ts.SyntaxKind.TemplateExpression:
1195
+ if (ts.isTemplateExpression(e))
1196
+ for (const span of list(e.templateSpans))
1197
+ this.expr(span.expression);
1198
+ return this.constNode(this.prim("string"));
1199
+ case ts.SyntaxKind.NumericLiteral:
1200
+ return this.constNode(this.prim("number"));
1201
+ case ts.SyntaxKind.BigIntLiteral:
1202
+ return this.constNode(this.prim("bigint"));
1203
+ case ts.SyntaxKind.TrueKeyword:
1204
+ case ts.SyntaxKind.FalseKeyword:
1205
+ return this.constNode(this.prim("boolean"));
1206
+ case ts.SyntaxKind.NullKeyword:
1207
+ return this.constNode(this.prim("null"));
1208
+ case ts.SyntaxKind.RegularExpressionLiteral:
1209
+ return this.constNode(this.builtin("RegExp.instance"));
1210
+ case ts.SyntaxKind.ThisKeyword:
1211
+ return this.currentFn !== null
1212
+ ? this.currentFn.thisNode
1213
+ : this.constNode(this.prim("undefined"));
1214
+ case ts.SyntaxKind.SuperKeyword:
1215
+ return this.constNode(this.top);
1216
+ }
1217
+ if (ts.isIdentifier(e))
1218
+ return this.identifier(e);
1219
+ if (ts.isObjectLiteralExpression(e))
1220
+ return this.objectLiteral(e);
1221
+ if (ts.isArrayLiteralExpression(e))
1222
+ return this.arrayLiteral(e);
1223
+ if (ts.isArrowFunction(e) || ts.isFunctionExpression(e)) {
1224
+ const n = this.newNode();
1225
+ this.add(n, this.fnAtom(e, null));
1226
+ if (ts.isFunctionExpression(e) && e.name !== undefined)
1227
+ this.add(this.binding(e), this.fnAtom(e, null));
1228
+ return n;
1229
+ }
1230
+ if (ts.isClassExpression(e)) {
1231
+ const n = this.newNode();
1232
+ this.add(n, this.classAtoms(e).cls);
1233
+ return n;
1234
+ }
1235
+ if (ts.isPropertyAccessExpression(e)) {
1236
+ this.noteSite(e);
1237
+ // `globalThis.Proxy` and the like are the modeled globals.
1238
+ const object = unparen(e.expression);
1239
+ if (ts.isIdentifier(object) &&
1240
+ object.text === "globalThis" &&
1241
+ MODELED_GLOBALS.has(e.name.text)) {
1242
+ const d = this.resolve(object);
1243
+ if (d === undefined || d.getSourceFile().isDeclarationFile)
1244
+ return this.globalNode(e.name.text);
1245
+ }
1246
+ const recv = this.expr(e.expression);
1247
+ const name = e.name.text;
1248
+ const dst = this.newNode();
1249
+ this.loadConstraint(recv, name, dst, e);
1250
+ this.ops.push({ kind: "read", recv, name, node: e });
1251
+ return dst;
1252
+ }
1253
+ if (ts.isElementAccessExpression(e)) {
1254
+ const recv = this.expr(e.expression);
1255
+ const key = unparen(e.argumentExpression);
1256
+ const dst = this.newNode();
1257
+ const name = ts.isStringLiteral(key) || ts.isNoSubstitutionTemplateLiteral(key) ? key.text : null;
1258
+ if (name !== null) {
1259
+ this.loadConstraint(recv, name, dst, e);
1260
+ this.ops.push({ kind: "read", recv, name, node: e });
1261
+ }
1262
+ else {
1263
+ this.expr(e.argumentExpression);
1264
+ this.computedLoad(recv, dst, e);
1265
+ this.ops.push({ kind: "computedRead", recv, name: null, node: e });
1266
+ }
1267
+ return dst;
1268
+ }
1269
+ if (ts.isCallExpression(e))
1270
+ return this.call(e);
1271
+ if (ts.isNewExpression(e))
1272
+ return this.newExpr(e);
1273
+ if (ts.isBinaryExpression(e))
1274
+ return this.binary(e);
1275
+ if (ts.isConditionalExpression(e)) {
1276
+ this.expr(e.condition);
1277
+ const n = this.newNode();
1278
+ this.edge(this.expr(e.whenTrue), n);
1279
+ this.edge(this.expr(e.whenFalse), n);
1280
+ return n;
1281
+ }
1282
+ if (ts.isAwaitExpression(e)) {
1283
+ const n = this.newNode();
1284
+ this.awaitInto(this.expr(e.expression), n);
1285
+ return n;
1286
+ }
1287
+ if (ts.isTypeOfExpression(e)) {
1288
+ this.expr(e.expression);
1289
+ return this.constNode(this.prim("string"));
1290
+ }
1291
+ if (ts.isVoidExpression(e)) {
1292
+ this.expr(e.expression);
1293
+ return this.constNode(this.prim("undefined"));
1294
+ }
1295
+ if (ts.isDeleteExpression(e)) {
1296
+ const target = unparen(e.expression);
1297
+ if (ts.isPropertyAccessExpression(target) || ts.isElementAccessExpression(target)) {
1298
+ const recv = this.expr(target.expression);
1299
+ const name = ts.isPropertyAccessExpression(target) ? target.name.text : null;
1300
+ this.ops.push({ kind: "delete", recv, name, node: e });
1301
+ }
1302
+ return this.constNode(this.prim("boolean"));
1303
+ }
1304
+ if (ts.isPrefixUnaryExpression(e) || ts.isPostfixUnaryExpression(e)) {
1305
+ const operand = e.operand;
1306
+ this.expr(operand);
1307
+ if (e.operator === ts.SyntaxKind.PlusPlusToken ||
1308
+ e.operator === ts.SyntaxKind.MinusMinusToken)
1309
+ this.assignTo(operand, this.constNode(this.prim("number")));
1310
+ if (ts.isPrefixUnaryExpression(e) && e.operator === ts.SyntaxKind.ExclamationToken)
1311
+ return this.constNode(this.prim("boolean"));
1312
+ return this.constNode(this.prim("number"));
1313
+ }
1314
+ if (ts.isSpreadElement(e))
1315
+ return this.expr(e.expression);
1316
+ if (ts.isTaggedTemplateExpression(e))
1317
+ return this.taggedTemplate(e);
1318
+ if (ts.isYieldExpression(e)) {
1319
+ if (e.expression !== undefined)
1320
+ this.sink(this.expr(e.expression), `yielded at ${locLabel(e)}`);
1321
+ return this.constNode(this.top);
1322
+ }
1323
+ if (ts.isMetaProperty(e))
1324
+ return this.constNode(this.top);
1325
+ // Anything else: evaluate children, answer ⊤.
1326
+ ts.forEachChild(e, (child) => {
1327
+ if (ts.isExpression(child))
1328
+ this.expr(child);
1329
+ return undefined;
1330
+ });
1331
+ return this.constNode(this.top);
1332
+ }
1333
+ identifier(id) {
1334
+ if (id.text === "undefined")
1335
+ return this.constNode(this.prim("undefined"));
1336
+ if (id.text === "arguments") {
1337
+ const fn = this.enclosingNonArrow();
1338
+ if (fn !== null) {
1339
+ const parent = id.parent;
1340
+ const forwarding = parent !== undefined && ts.isSpreadElement(parent);
1341
+ if (!forwarding)
1342
+ fn.usesArguments = true;
1343
+ const arr = this.syntheticArray(id, "arguments");
1344
+ for (const p of fn.params)
1345
+ this.edge(p, this.element(arr));
1346
+ return this.constNode(arr);
1347
+ }
1348
+ }
1349
+ const decl = this.resolve(id);
1350
+ if (decl === undefined)
1351
+ return this.globalNode(id.text);
1352
+ if (decl.getSourceFile().isDeclarationFile)
1353
+ return this.globalNode(id.text);
1354
+ if (!this.files.includes(decl.getSourceFile()))
1355
+ return this.constNode(this.top);
1356
+ if (ts.isFunctionDeclaration(decl)) {
1357
+ const b = this.binding(decl);
1358
+ const saved = this.currentFn;
1359
+ this.currentFn = null;
1360
+ this.add(b, this.fnAtom(decl, null));
1361
+ this.currentFn = saved;
1362
+ return b;
1363
+ }
1364
+ if (ts.isClassDeclaration(decl) || ts.isClassExpression(decl)) {
1365
+ const b = this.binding(decl);
1366
+ this.add(b, this.classAtoms(decl).cls);
1367
+ return b;
1368
+ }
1369
+ if (ts.isFunctionExpression(decl))
1370
+ return this.binding(decl);
1371
+ if (ts.isImportSpecifier(decl) ||
1372
+ ts.isImportClause(decl) ||
1373
+ ts.isNamespaceImport(decl) ||
1374
+ ts.isImportEqualsDeclaration(decl))
1375
+ return this.constNode(this.top);
1376
+ if (ts.isSourceFile(decl) || ts.isModuleDeclaration(decl))
1377
+ return this.namespaceNode(decl);
1378
+ // A CommonJS export the checker resolved an import or require binding
1379
+ // to (`module.exports = { name }`, `exports.name = v`): the member of the
1380
+ // module's exports.
1381
+ const exported = cjsExportName(decl);
1382
+ if (exported !== null && decl.getSourceFile() !== id.getSourceFile()) {
1383
+ const dst = this.newNode();
1384
+ this.loadConstraint(this.namespaceNode(decl.getSourceFile()), exported, dst, id);
1385
+ return dst;
1386
+ }
1387
+ return this.narrowed(id, decl, this.binding(decl));
1388
+ }
1389
+ /** Flow narrowing at guarded references (S1 handles the guards hot code
1390
+ * uses: `x instanceof C` and calls of predicate functions whose body is
1391
+ * `… && x instanceof C`, in the true arm of an `if`, `?:` or `&&`). The
1392
+ * narrowed value keeps the guard's class arms and ⊤. */
1393
+ narrowed(id, decl, value) {
1394
+ let child = id;
1395
+ let p = id.parent;
1396
+ while (p !== undefined && !ts.isFunctionLike(p) && !ts.isSourceFile(p)) {
1397
+ let cond;
1398
+ if (ts.isIfStatement(p) && p.thenStatement === child)
1399
+ cond = p.expression;
1400
+ else if (ts.isConditionalExpression(p) && p.whenTrue === child)
1401
+ cond = p.condition;
1402
+ else if (ts.isBinaryExpression(p) &&
1403
+ p.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken &&
1404
+ p.right === child)
1405
+ cond = p.left;
1406
+ if (cond !== undefined) {
1407
+ const cls = this.guardClass(cond, decl);
1408
+ if (cls !== null) {
1409
+ const out = this.newNode();
1410
+ this.on(value, (a) => {
1411
+ if (a.kind === "top")
1412
+ this.add(out, a);
1413
+ else if (cls === "Promise"
1414
+ ? a.kind === "promise"
1415
+ : a.kind === "instance" &&
1416
+ a.node !== undefined &&
1417
+ this.classChain(a.node).includes(cls))
1418
+ this.add(out, a);
1419
+ });
1420
+ return out;
1421
+ }
1422
+ }
1423
+ child = p;
1424
+ p = p.parent;
1425
+ }
1426
+ return value;
1427
+ }
1428
+ /** The class a condition proves `decl`'s value an instance of, if any. */
1429
+ guardClass(cond, decl) {
1430
+ const e = unparen(cond);
1431
+ if (ts.isBinaryExpression(e)) {
1432
+ if (e.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken)
1433
+ return this.guardClass(e.left, decl) ?? this.guardClass(e.right, decl);
1434
+ if (e.operatorToken.kind !== ts.SyntaxKind.InstanceOfKeyword)
1435
+ return null;
1436
+ const l = unparen(e.left);
1437
+ if (!ts.isIdentifier(l) || this.resolve(l) !== decl)
1438
+ return null;
1439
+ return this.instanceofTarget(e.right);
1440
+ }
1441
+ if (ts.isCallExpression(e) &&
1442
+ ts.isIdentifier(unparen(e.expression)) &&
1443
+ e.arguments.nodes.length === 1) {
1444
+ const arg = unparen(e.arguments.nodes[0]);
1445
+ if (!ts.isIdentifier(arg) || this.resolve(arg) !== decl)
1446
+ return null;
1447
+ const fnDecl = this.resolve(unparen(e.expression));
1448
+ let fn = fnDecl;
1449
+ if (fn !== undefined && ts.isVariableDeclaration(fn) && fn.initializer !== undefined)
1450
+ fn = unparen(fn.initializer);
1451
+ if (fn === undefined ||
1452
+ !(ts.isArrowFunction(fn) || ts.isFunctionDeclaration(fn) || ts.isFunctionExpression(fn)))
1453
+ return null;
1454
+ const param = fn.parameters.nodes[0];
1455
+ if (param === undefined || !ts.isIdentifier(param.name))
1456
+ return null;
1457
+ let body = fn.body;
1458
+ if (body !== undefined && ts.isBlock(body)) {
1459
+ const stmts = body.statements.nodes;
1460
+ body =
1461
+ stmts.length === 1 && ts.isReturnStatement(stmts[0]) ? stmts[0].expression : undefined;
1462
+ }
1463
+ if (body === undefined)
1464
+ return null;
1465
+ return this.predicateClass(body, param);
1466
+ }
1467
+ return null;
1468
+ }
1469
+ /** `… && p instanceof C` in a predicate body over parameter `p`. */
1470
+ predicateClass(e, param) {
1471
+ const u = unparen(e);
1472
+ if (!ts.isBinaryExpression(u))
1473
+ return null;
1474
+ if (u.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken)
1475
+ return this.predicateClass(u.right, param) ?? this.predicateClass(u.left, param);
1476
+ if (u.operatorToken.kind !== ts.SyntaxKind.InstanceOfKeyword)
1477
+ return null;
1478
+ const l = unparen(u.left);
1479
+ if (!ts.isIdentifier(l) || this.resolve(l) !== param)
1480
+ return null;
1481
+ return this.instanceofTarget(u.right);
1482
+ }
1483
+ instanceofTarget(right) {
1484
+ const r = unparen(right);
1485
+ if (!ts.isIdentifier(r))
1486
+ return null;
1487
+ const d = this.resolve(r);
1488
+ if (d === undefined || d.getSourceFile().isDeclarationFile)
1489
+ return r.text === "Promise" ? "Promise" : null;
1490
+ return ts.isClassLikeDeclaration(d) ? d : null;
1491
+ }
1492
+ namespaces = new Map();
1493
+ /** Module namespaces: a CommonJS module's `module.exports` value is the
1494
+ * namespace's `exports` field, and member reads see its members too. */
1495
+ namespaceAtoms = new Set();
1496
+ /** `import * as ns`: an object whose fields are the module's exports. */
1497
+ namespaceNode(mod) {
1498
+ const existing = this.namespaces.get(mod);
1499
+ if (existing !== undefined)
1500
+ return existing;
1501
+ const n = this.newNode();
1502
+ this.namespaces.set(mod, n);
1503
+ const atom = this.atoms.intern(`ns:${this.nodeKey(mod)}`, () => ({
1504
+ kind: "object",
1505
+ label: `namespace ${shortFile(mod.fileName ?? "")}`,
1506
+ node: mod,
1507
+ }));
1508
+ this.namespaceAtoms.add(atom);
1509
+ this.add(n, atom);
1510
+ const sym = this.checker.getSymbolAtLocation(mod);
1511
+ if (sym !== undefined) {
1512
+ for (const ex of this.checker.getExportsOfModule(sym)) {
1513
+ let target = ex;
1514
+ if (target.flags & ts.SymbolFlags.Alias) {
1515
+ try {
1516
+ target = this.checker.getAliasedSymbol(target);
1517
+ }
1518
+ catch {
1519
+ continue;
1520
+ }
1521
+ }
1522
+ const d = target.valueDeclaration ?? target.declarations[0];
1523
+ if (d === undefined)
1524
+ continue;
1525
+ const value = this.declValue(d);
1526
+ if (value !== null)
1527
+ this.edge(value, this.field(atom, String(ex.escapedName)));
1528
+ }
1529
+ }
1530
+ return n;
1531
+ }
1532
+ declValue(d) {
1533
+ if (d.getSourceFile().isDeclarationFile || !this.files.includes(d.getSourceFile()))
1534
+ return null;
1535
+ if (ts.isFunctionDeclaration(d)) {
1536
+ const b = this.binding(d);
1537
+ const saved = this.currentFn;
1538
+ this.currentFn = null;
1539
+ this.add(b, this.fnAtom(d, null));
1540
+ this.currentFn = saved;
1541
+ return b;
1542
+ }
1543
+ if (ts.isClassDeclaration(d)) {
1544
+ const b = this.binding(d);
1545
+ this.add(b, this.classAtoms(d).cls);
1546
+ return b;
1547
+ }
1548
+ if (ts.isVariableDeclaration(d) || ts.isBindingElement(d) || ts.isParameter(d))
1549
+ return this.binding(d);
1550
+ if (ts.isSourceFile(d))
1551
+ return this.namespaceNode(d);
1552
+ return null;
1553
+ }
1554
+ globalNode(name) {
1555
+ if (MODELED_GLOBALS.has(name))
1556
+ return this.constNode(this.builtin(name));
1557
+ if (name === "NaN" || name === "Infinity")
1558
+ return this.constNode(this.prim("number"));
1559
+ return this.constNode(this.top);
1560
+ }
1561
+ enclosingNonArrow() {
1562
+ const fn = this.currentFn;
1563
+ if (fn === null)
1564
+ return null;
1565
+ if (!fn.isArrow)
1566
+ return fn;
1567
+ // An arrow's `arguments` is its enclosing function's.
1568
+ let p = fn.node.parent;
1569
+ while (p !== undefined) {
1570
+ if (ts.isFunctionLike(p) && !ts.isArrowFunction(p))
1571
+ return (this.functions.get(this.ctxKey(p)) ?? this.functions.get(`|${this.nodeKey(p)}`) ?? null);
1572
+ p = p.parent;
1573
+ }
1574
+ return null;
1575
+ }
1576
+ objectLiteral(e) {
1577
+ const keys = [];
1578
+ let keysKnown = true;
1579
+ let hasAccessor = false;
1580
+ let hasProto = false;
1581
+ let hasComputedKey = false;
1582
+ const spreads = [];
1583
+ const inPackage = isPackageJsFile(e.getSourceFile());
1584
+ const label = () => `{${keys.slice(0, 6).join(",")}${keys.length > 6 ? ",…" : ""}${keysKnown ? "" : ",…"}}@${locLabel(e)}`;
1585
+ // keys first, so the label is complete
1586
+ for (const p of list(e.properties)) {
1587
+ if (ts.isSpreadAssignment(p)) {
1588
+ keysKnown = false;
1589
+ continue;
1590
+ }
1591
+ const name = p.name;
1592
+ const key = name !== undefined ? propertyNameText(name) : null;
1593
+ if (key === null) {
1594
+ hasComputedKey = true;
1595
+ keysKnown = false;
1596
+ continue;
1597
+ }
1598
+ if (key === "__proto__" && ts.isPropertyAssignment(p) && !ts.isComputedPropertyName(p.name))
1599
+ hasProto = true;
1600
+ if (!keys.includes(key))
1601
+ keys.push(key);
1602
+ }
1603
+ const atom = this.atoms.intern(`obj:${this.nodeKey(e)}`, () => ({
1604
+ kind: "object",
1605
+ label: label(),
1606
+ node: e,
1607
+ }));
1608
+ const n = this.newNode();
1609
+ this.add(n, atom);
1610
+ for (const p of list(e.properties)) {
1611
+ if (ts.isSpreadAssignment(p)) {
1612
+ const src = this.expr(p.expression);
1613
+ spreads.push(src);
1614
+ this.copyFields(src, atom, p);
1615
+ continue;
1616
+ }
1617
+ if (ts.isGetAccessorDeclaration(p) || ts.isSetAccessorDeclaration(p)) {
1618
+ hasAccessor = true;
1619
+ const info = this.functionInfo(p, null);
1620
+ this.activate(info);
1621
+ this.add(info.thisNode, atom);
1622
+ const key = propertyNameText(p.name);
1623
+ if (key !== null && ts.isGetAccessorDeclaration(p))
1624
+ this.edge(info.ret, this.field(atom, key));
1625
+ continue;
1626
+ }
1627
+ const name = p.name;
1628
+ const key = name !== undefined ? propertyNameText(name) : null;
1629
+ if (name !== undefined && ts.isComputedPropertyName(name))
1630
+ this.expr(name.expression);
1631
+ let value;
1632
+ if (ts.isPropertyAssignment(p))
1633
+ value = this.expr(p.initializer);
1634
+ else if (ts.isShorthandPropertyAssignment(p)) {
1635
+ const sym = this.checker.getShorthandAssignmentValueSymbol(p);
1636
+ const d = sym?.valueDeclaration ?? sym?.declarations[0];
1637
+ const id = p.name;
1638
+ value = d !== undefined ? (this.declValue(d) ?? this.identifier(id)) : this.identifier(id);
1639
+ }
1640
+ else if (ts.isMethodDeclaration(p)) {
1641
+ const fa = this.fnAtom(p, null);
1642
+ this.add(this.infoOfAtom(fa).thisNode, atom);
1643
+ value = this.constNode(fa);
1644
+ }
1645
+ else
1646
+ continue;
1647
+ if (key !== null)
1648
+ this.edge(value, this.field(atom, key));
1649
+ else
1650
+ this.edge(value, this.anyField(atom));
1651
+ }
1652
+ if (!this.siteAtoms.has(atom) && this.siteAtoms.add(atom))
1653
+ this.sites.push({
1654
+ atom,
1655
+ node: e,
1656
+ kind: "object",
1657
+ keys: keysKnown ? keys : null,
1658
+ hasAccessor,
1659
+ hasProto,
1660
+ hasComputedKey,
1661
+ spreads,
1662
+ inPackage,
1663
+ });
1664
+ return n;
1665
+ }
1666
+ /** Values written under unknown keys. */
1667
+ anyField(atom) {
1668
+ return this.field(atom, "*");
1669
+ }
1670
+ /** Loads waiting for an atom's first write of a field, by field name. */
1671
+ fieldReaders = new Map();
1672
+ /** dst ⊇ the values written to field `name` of `atom`, now and later,
1673
+ * without creating the field for atoms that have none. */
1674
+ fieldInto(atom, name, dst) {
1675
+ const id = this.fields.get(atom)?.get(name);
1676
+ if (id !== undefined) {
1677
+ this.edge(id, dst);
1678
+ return;
1679
+ }
1680
+ let byName = this.fieldReaders.get(atom);
1681
+ if (byName === undefined) {
1682
+ byName = new Map();
1683
+ this.fieldReaders.set(atom, byName);
1684
+ }
1685
+ let readers = byName.get(name);
1686
+ if (readers === undefined) {
1687
+ readers = [];
1688
+ byName.set(name, readers);
1689
+ }
1690
+ readers.push(dst);
1691
+ }
1692
+ /** dst ⊇ the values written to `atom` under unknown keys, now and later. */
1693
+ unknownKeysInto(atom, dst) {
1694
+ this.fieldInto(atom, "*", dst);
1695
+ }
1696
+ copyFields(src, dstAtom, site) {
1697
+ this.on(src, (a) => {
1698
+ if (a.kind === "top") {
1699
+ this.edge(this.constNode(this.top), this.anyField(dstAtom));
1700
+ return;
1701
+ }
1702
+ if (a.kind === "prim" || a.kind === "builtin")
1703
+ return;
1704
+ if (a.kind === "array") {
1705
+ this.edge(this.element(a), this.anyField(dstAtom));
1706
+ return;
1707
+ }
1708
+ // Copy every own field the source has, now and later.
1709
+ const fm = this.fields.get(a);
1710
+ const copied = new Set();
1711
+ const copy = () => {
1712
+ for (const [name, id] of this.fields.get(a) ?? new Map()) {
1713
+ if (copied.has(name))
1714
+ continue;
1715
+ copied.add(name);
1716
+ this.edge(id, this.field(dstAtom, name));
1717
+ }
1718
+ };
1719
+ copy();
1720
+ if (fm === undefined)
1721
+ this.fields.set(a, new Map());
1722
+ this.lateCopies.push(copy);
1723
+ if (a.kind === "instance" || a.kind === "dictionary" || a.kind === "collection")
1724
+ this.edge(this.constNode(this.top), this.anyField(dstAtom));
1725
+ void site;
1726
+ });
1727
+ }
1728
+ /** Field copies re-run after solving rounds (fields created later). */
1729
+ lateCopies = [];
1730
+ /** node ⊇ the own field and element values of every value in it, now and
1731
+ * later: the values JSON.stringify serializes. */
1732
+ childrenInto(node) {
1733
+ this.on(node, (a) => {
1734
+ if (a.kind !== "object" &&
1735
+ a.kind !== "array" &&
1736
+ a.kind !== "instance" &&
1737
+ a.kind !== "dictionary")
1738
+ return;
1739
+ const seen = new Set();
1740
+ const copy = () => {
1741
+ for (const [name, id] of this.fields.get(a) ?? new Map()) {
1742
+ if (seen.has(name) || name.startsWith("#"))
1743
+ continue;
1744
+ seen.add(name);
1745
+ this.edge(id, node);
1746
+ }
1747
+ const el = this.elements.get(a);
1748
+ if (el !== undefined && !seen.has("[]")) {
1749
+ seen.add("[]");
1750
+ this.edge(el, node);
1751
+ }
1752
+ };
1753
+ copy();
1754
+ this.lateCopies.push(copy);
1755
+ });
1756
+ }
1757
+ /** JSON.stringify's call of `value.toJSON(key)` on an object, array or function that may
1758
+ * have one (a class member, an own field, or a write under an unknown key, once it exists);
1759
+ * the result goes to `out`. */
1760
+ callToJSON(value, key, out, site) {
1761
+ if (value.kind !== "object" &&
1762
+ value.kind !== "instance" &&
1763
+ value.kind !== "dictionary" &&
1764
+ value.kind !== "array" &&
1765
+ value.kind !== "function" &&
1766
+ value.kind !== "class")
1767
+ return;
1768
+ let called = false;
1769
+ const call = () => {
1770
+ if (called)
1771
+ return;
1772
+ const fields = this.fields.get(value);
1773
+ const has = fields?.has("toJSON") === true ||
1774
+ fields?.has("*") === true ||
1775
+ ((value.kind === "instance" || value.kind === "class") &&
1776
+ this.lookupMember(value.node, "toJSON", value.kind === "class") !== null);
1777
+ if (!has)
1778
+ return;
1779
+ called = true;
1780
+ const fn = this.newNode();
1781
+ this.loadAtom(value, "toJSON", fn, site);
1782
+ this.invoke(fn, this.constNode(value), [key], false, out, site);
1783
+ };
1784
+ call();
1785
+ if (!called)
1786
+ this.lateCopies.push(call);
1787
+ }
1788
+ arrayLiteral(e) {
1789
+ const atom = this.atoms.intern(`arr:${this.nodeKey(e)}`, () => ({
1790
+ kind: "array",
1791
+ label: `[]@${locLabel(e)}`,
1792
+ node: e,
1793
+ }));
1794
+ const n = this.newNode();
1795
+ this.add(n, atom);
1796
+ const el = this.element(atom);
1797
+ let hasHole = false;
1798
+ for (const item of list(e.elements)) {
1799
+ if (ts.isOmittedExpression(item)) {
1800
+ hasHole = true;
1801
+ continue;
1802
+ }
1803
+ if (ts.isSpreadElement(item))
1804
+ this.iterateInto(this.expr(item.expression), el, item);
1805
+ else
1806
+ this.edge(this.expr(item), el);
1807
+ }
1808
+ if (!this.siteAtoms.has(atom) && this.siteAtoms.add(atom))
1809
+ this.sites.push({
1810
+ atom,
1811
+ node: e,
1812
+ kind: "array",
1813
+ keys: null,
1814
+ hasAccessor: false,
1815
+ hasProto: hasHole,
1816
+ hasComputedKey: false,
1817
+ spreads: [],
1818
+ inPackage: isPackageJsFile(e.getSourceFile()),
1819
+ });
1820
+ return n;
1821
+ }
1822
+ binary(e) {
1823
+ const op = e.operatorToken.kind;
1824
+ if (op === ts.SyntaxKind.EqualsToken) {
1825
+ const value = this.expr(e.right);
1826
+ this.assignTo(e.left, value);
1827
+ return value;
1828
+ }
1829
+ if (op === ts.SyntaxKind.BarBarEqualsToken ||
1830
+ op === ts.SyntaxKind.QuestionQuestionEqualsToken ||
1831
+ op === ts.SyntaxKind.AmpersandAmpersandEqualsToken) {
1832
+ const n = this.newNode();
1833
+ this.edge(this.expr(e.left), n);
1834
+ const value = this.expr(e.right);
1835
+ this.edge(value, n);
1836
+ this.assignTo(e.left, value);
1837
+ return n;
1838
+ }
1839
+ if (op >= ts.SyntaxKind.FirstCompoundAssignment && op <= ts.SyntaxKind.LastCompoundAssignment) {
1840
+ this.expr(e.left);
1841
+ this.expr(e.right);
1842
+ const result = this.constNode(op === ts.SyntaxKind.PlusEqualsToken ? this.top : this.prim("number"));
1843
+ if (op === ts.SyntaxKind.PlusEqualsToken) {
1844
+ this.nodes[result].atoms.clear();
1845
+ this.add(result, this.prim("string"));
1846
+ this.add(result, this.prim("number"));
1847
+ }
1848
+ this.assignTo(e.left, result);
1849
+ return result;
1850
+ }
1851
+ if (op === ts.SyntaxKind.BarBarToken ||
1852
+ op === ts.SyntaxKind.QuestionQuestionToken ||
1853
+ op === ts.SyntaxKind.AmpersandAmpersandToken) {
1854
+ const n = this.newNode();
1855
+ this.edge(this.expr(e.left), n);
1856
+ this.edge(this.expr(e.right), n);
1857
+ return n;
1858
+ }
1859
+ if (op === ts.SyntaxKind.CommaToken) {
1860
+ this.expr(e.left);
1861
+ return this.expr(e.right);
1862
+ }
1863
+ const l = this.expr(e.left);
1864
+ const r = this.expr(e.right);
1865
+ switch (op) {
1866
+ case ts.SyntaxKind.EqualsEqualsEqualsToken:
1867
+ case ts.SyntaxKind.ExclamationEqualsEqualsToken:
1868
+ case ts.SyntaxKind.EqualsEqualsToken:
1869
+ case ts.SyntaxKind.ExclamationEqualsToken:
1870
+ case ts.SyntaxKind.LessThanToken:
1871
+ case ts.SyntaxKind.LessThanEqualsToken:
1872
+ case ts.SyntaxKind.GreaterThanToken:
1873
+ case ts.SyntaxKind.GreaterThanEqualsToken:
1874
+ case ts.SyntaxKind.InstanceOfKeyword:
1875
+ case ts.SyntaxKind.InKeyword:
1876
+ if (op === ts.SyntaxKind.InKeyword)
1877
+ this.ops.push({ kind: "computedRead", recv: r, name: null, node: e });
1878
+ return this.constNode(this.prim("boolean"));
1879
+ case ts.SyntaxKind.PlusToken: {
1880
+ const n = this.newNode();
1881
+ const strOrNum = (a) => {
1882
+ this.add(n, a.kind === "prim" && a.label === "number" ? this.prim("number") : this.prim("string"));
1883
+ if (a.kind === "prim" &&
1884
+ (a.label === "boolean" || a.label === "null" || a.label === "undefined"))
1885
+ this.add(n, this.prim("number"));
1886
+ if (a.kind === "top")
1887
+ this.add(n, this.prim("number"));
1888
+ };
1889
+ this.on(l, strOrNum);
1890
+ this.on(r, strOrNum);
1891
+ return n;
1892
+ }
1893
+ default:
1894
+ return this.constNode(this.prim("number"));
1895
+ }
1896
+ }
1897
+ assignTo(target, value) {
1898
+ const t = unparen(target);
1899
+ if (ts.isIdentifier(t)) {
1900
+ const decl = this.resolve(t);
1901
+ if (decl === undefined || decl.getSourceFile().isDeclarationFile) {
1902
+ this.sink(value, `global write at ${locLabel(t)}`);
1903
+ return;
1904
+ }
1905
+ this.edge(value, this.binding(decl));
1906
+ return;
1907
+ }
1908
+ if (ts.isPropertyAccessExpression(t)) {
1909
+ const recv = this.expr(t.expression);
1910
+ this.storeConstraint(recv, t.name.text, value, t);
1911
+ this.ops.push({
1912
+ kind: t.name.text === "length" ? "lengthWrite" : "write",
1913
+ recv,
1914
+ name: t.name.text,
1915
+ node: t,
1916
+ });
1917
+ return;
1918
+ }
1919
+ if (ts.isElementAccessExpression(t)) {
1920
+ const recv = this.expr(t.expression);
1921
+ const key = unparen(t.argumentExpression);
1922
+ if (ts.isStringLiteral(key) || ts.isNoSubstitutionTemplateLiteral(key)) {
1923
+ this.storeConstraint(recv, key.text, value, t);
1924
+ this.ops.push({ kind: "write", recv, name: key.text, node: t });
1925
+ }
1926
+ else {
1927
+ this.expr(t.argumentExpression);
1928
+ this.computedStore(recv, value, t);
1929
+ this.ops.push({ kind: "computedWrite", recv, name: null, node: t });
1930
+ }
1931
+ return;
1932
+ }
1933
+ if (ts.isObjectLiteralExpression(t)) {
1934
+ for (const p of list(t.properties)) {
1935
+ if (ts.isPropertyAssignment(p)) {
1936
+ const key = propertyNameText(p.name);
1937
+ const n = this.newNode();
1938
+ if (key !== null)
1939
+ this.loadConstraint(value, key, n, p);
1940
+ else
1941
+ this.add(n, this.top);
1942
+ this.assignTo(p.initializer, n);
1943
+ }
1944
+ else if (ts.isShorthandPropertyAssignment(p)) {
1945
+ const n = this.newNode();
1946
+ const id = p.name;
1947
+ this.loadConstraint(value, id.text, n, p);
1948
+ this.assignTo(id, n);
1949
+ }
1950
+ }
1951
+ return;
1952
+ }
1953
+ if (ts.isArrayLiteralExpression(t)) {
1954
+ for (const el of list(t.elements)) {
1955
+ if (ts.isOmittedExpression(el))
1956
+ continue;
1957
+ const n = this.newNode();
1958
+ this.iterateInto(value, n, el);
1959
+ this.assignTo(ts.isSpreadElement(el) ? el.expression : el, n);
1960
+ }
1961
+ }
1962
+ }
1963
+ // ---- loads and stores ------------------------------------------------------------
1964
+ loadConstraint(recv, name, dst, site) {
1965
+ this.on(recv, (a) => this.loadAtom(a, name, dst, site));
1966
+ }
1967
+ loadAtom(a, name, dst, site) {
1968
+ switch (a.kind) {
1969
+ case "top":
1970
+ this.add(dst, this.top);
1971
+ return;
1972
+ case "prim":
1973
+ if (name === "length" && a.label === "string")
1974
+ this.add(dst, this.prim("number"));
1975
+ else if (a.label === "string" || a.label === "number" || a.label === "boolean")
1976
+ this.add(dst, this.builtin(`${a.label}.${name}`, a));
1977
+ return;
1978
+ case "instance": {
1979
+ const decl = a.node;
1980
+ if (name === "constructor") {
1981
+ // An own `constructor` field, written by name or under an unknown key, shadows the class.
1982
+ this.add(dst, this.classAtoms(decl).cls);
1983
+ this.fieldInto(a, name, dst);
1984
+ this.unknownKeysInto(a, dst);
1985
+ return;
1986
+ }
1987
+ const member = this.lookupMember(decl, name, false);
1988
+ if (member?.kind === "method")
1989
+ this.add(dst, this.fnAtom(member.method, this.ownerOf(member.method), this.receiverCtx(a)));
1990
+ if (member !== null && member.get !== undefined) {
1991
+ const g = this.functionInfo(member.get, this.ownerOf(member.get), this.receiverCtx(a));
1992
+ this.activate(g);
1993
+ this.add(g.thisNode, a);
1994
+ this.edge(g.ret, dst);
1995
+ this.edgeFor(site, g);
1996
+ return;
1997
+ }
1998
+ if (this.classChain(decl).some((c) => this.baseClass(c) === undefined))
1999
+ this.add(dst, this.top);
2000
+ this.edge(this.field(a, name), dst);
2001
+ this.unknownKeysInto(a, dst);
2002
+ return;
2003
+ }
2004
+ case "class": {
2005
+ const decl = a.node;
2006
+ if (name === "prototype" || name === "name") {
2007
+ this.add(dst, name === "prototype" ? this.top : this.prim("string"));
2008
+ this.fieldInto(a, name, dst);
2009
+ this.unknownKeysInto(a, dst);
2010
+ return;
2011
+ }
2012
+ const member = this.lookupMember(decl, name, true);
2013
+ if (member?.kind === "method")
2014
+ this.add(dst, this.fnAtom(member.method, this.ownerOf(member.method), this.receiverCtx(a)));
2015
+ if (member?.get !== undefined) {
2016
+ const g = this.functionInfo(member.get, this.ownerOf(member.get), this.receiverCtx(a));
2017
+ this.activate(g);
2018
+ this.add(g.thisNode, a);
2019
+ this.edge(g.ret, dst);
2020
+ return;
2021
+ }
2022
+ // static fields of the class and its bases
2023
+ for (const c of this.classChain(decl)) {
2024
+ const cls = this.classAtoms(c).cls;
2025
+ this.edge(this.field(cls, name), dst);
2026
+ this.unknownKeysInto(cls, dst);
2027
+ }
2028
+ return;
2029
+ }
2030
+ case "function":
2031
+ // An own field, written by name or under an unknown key, shadows a builtin member.
2032
+ if (name === "call" || name === "apply" || name === "bind")
2033
+ this.add(dst, this.builtin(`function.${name}`, a));
2034
+ else if (name === "prototype") {
2035
+ // The default prototype object, or what the program assigns.
2036
+ this.add(dst, this.protoAtom(a));
2037
+ this.edge(this.field(a, "prototype"), dst);
2038
+ }
2039
+ else if (name === "name")
2040
+ this.add(dst, this.prim("string"));
2041
+ else if (name === "length")
2042
+ this.add(dst, this.prim("number"));
2043
+ else {
2044
+ this.edge(this.field(a, name), dst);
2045
+ this.unknownKeysInto(a, dst);
2046
+ return;
2047
+ }
2048
+ this.fieldInto(a, name, dst);
2049
+ this.unknownKeysInto(a, dst);
2050
+ return;
2051
+ case "array":
2052
+ if (name === "length")
2053
+ this.add(dst, this.prim("number"));
2054
+ else if (/^\d+$/.test(name))
2055
+ this.edge(this.element(a), dst);
2056
+ else {
2057
+ // A named property, written by name or under an unknown key; an own field shadows a method.
2058
+ if (ARRAY_METHODS.has(name)) {
2059
+ this.add(dst, this.builtin(`array.${name}`, a));
2060
+ this.fieldInto(a, name, dst);
2061
+ }
2062
+ else
2063
+ this.edge(this.field(a, name), dst);
2064
+ this.unknownKeysInto(a, dst);
2065
+ }
2066
+ return;
2067
+ case "object": {
2068
+ this.edge(this.field(a, name), dst);
2069
+ this.edge(this.anyField(a), dst);
2070
+ if (this.namespaceAtoms.has(a) && name !== "exports") {
2071
+ this.loadConstraint(this.field(a, "exports"), name, dst, site);
2072
+ }
2073
+ // `new F()` instances read through F's prototype objects.
2074
+ const fn = this.fnOfInstance.get(a);
2075
+ if (fn !== undefined) {
2076
+ const protos = this.newNode();
2077
+ this.add(protos, this.protoAtom(fn));
2078
+ this.edge(this.field(fn, "prototype"), protos);
2079
+ this.on(protos, (proto) => {
2080
+ if (proto.kind === "object") {
2081
+ // A method stored under a computed key (`F.prototype[k] = fn`)
2082
+ // may be any name.
2083
+ this.edge(this.field(proto, name), dst);
2084
+ this.edge(this.anyField(proto), dst);
2085
+ }
2086
+ else if (proto.kind === "top")
2087
+ this.add(dst, this.top);
2088
+ });
2089
+ return;
2090
+ }
2091
+ if (name === "constructor" || name === "hasOwnProperty" || name === "toString")
2092
+ this.add(dst, this.builtin(`object.${name}`, a));
2093
+ return;
2094
+ }
2095
+ case "dictionary":
2096
+ this.edge(this.anyField(a), dst);
2097
+ this.edge(this.field(a, name), dst);
2098
+ return;
2099
+ case "promise":
2100
+ if (name === "then" || name === "catch" || name === "finally")
2101
+ this.add(dst, this.builtin(`promise.${name}`, a));
2102
+ return;
2103
+ case "collection":
2104
+ if (name === "size")
2105
+ this.add(dst, this.prim("number"));
2106
+ else
2107
+ this.add(dst, this.builtin(`collection.${name}`, a));
2108
+ return;
2109
+ case "builtin":
2110
+ this.loadBuiltin(a, name, dst);
2111
+ return;
2112
+ }
2113
+ void site;
2114
+ }
2115
+ ownerOf(member) {
2116
+ const p = member.parent;
2117
+ return p !== undefined && ts.isClassLikeDeclaration(p) ? p : null;
2118
+ }
2119
+ loadBuiltin(a, name, dst) {
2120
+ const path = a.path ?? "";
2121
+ if (path === "Number" &&
2122
+ (name === "MAX_SAFE_INTEGER" ||
2123
+ name === "MIN_SAFE_INTEGER" ||
2124
+ name === "EPSILON" ||
2125
+ name === "MAX_VALUE" ||
2126
+ name === "MIN_VALUE" ||
2127
+ name === "POSITIVE_INFINITY" ||
2128
+ name === "NEGATIVE_INFINITY" ||
2129
+ name === "NaN"))
2130
+ this.add(dst, this.prim("number"));
2131
+ else if (path === "Math" && /^[A-Z0-9_]+$/.test(name))
2132
+ this.add(dst, this.prim("number"));
2133
+ else if (path === "Symbol")
2134
+ this.add(dst, this.prim("symbol"));
2135
+ else if (path === "Error.instance" || path === "error") {
2136
+ if (name === "message" || name === "stack" || name === "name")
2137
+ this.add(dst, this.prim("string"));
2138
+ else
2139
+ this.add(dst, this.top);
2140
+ }
2141
+ else if (a.receiver === undefined &&
2142
+ MODELED_GLOBALS.has(path.split(".")[0]) &&
2143
+ path.split(".").length < 4)
2144
+ this.add(dst, this.builtin(`${path}.${name}`));
2145
+ else if (path === "RegExp.instance")
2146
+ this.add(dst, this.builtin(`regexp.${name}`, a));
2147
+ else
2148
+ this.add(dst, this.top);
2149
+ }
2150
+ storeConstraint(recv, name, value, site) {
2151
+ this.on(recv, (a) => {
2152
+ switch (a.kind) {
2153
+ case "top":
2154
+ this.noteTopWrite(name, site);
2155
+ this.sink(value, `stored into ⊤.${name} at ${locLabel(site)}`);
2156
+ return;
2157
+ case "instance": {
2158
+ const member = this.lookupMember(a.node, name, false);
2159
+ if (member?.set !== undefined) {
2160
+ const s = this.functionInfo(member.set, this.ownerOf(member.set), this.receiverCtx(a));
2161
+ this.activate(s);
2162
+ this.add(s.thisNode, a);
2163
+ if (s.params[0] !== undefined)
2164
+ this.edge(value, s.params[0]);
2165
+ return;
2166
+ }
2167
+ this.edge(value, this.field(a, name));
2168
+ return;
2169
+ }
2170
+ case "class":
2171
+ case "function":
2172
+ case "object":
2173
+ case "dictionary":
2174
+ this.edge(value, this.field(a, name));
2175
+ return;
2176
+ case "array":
2177
+ if (/^\d+$/.test(name))
2178
+ this.edge(value, this.element(a));
2179
+ else if (name !== "length")
2180
+ this.edge(value, this.field(a, name));
2181
+ return;
2182
+ case "prim":
2183
+ return;
2184
+ default:
2185
+ this.sink(value, `stored into ${a.label} at ${locLabel(site)}`);
2186
+ }
2187
+ });
2188
+ }
2189
+ computedLoad(recv, dst, site) {
2190
+ this.on(recv, (a) => {
2191
+ switch (a.kind) {
2192
+ case "top":
2193
+ this.add(dst, this.top);
2194
+ return;
2195
+ case "array":
2196
+ case "collection":
2197
+ this.edge(this.element(a), dst);
2198
+ return;
2199
+ case "prim":
2200
+ if (a.label === "string")
2201
+ this.add(dst, this.prim("string"));
2202
+ return;
2203
+ case "object":
2204
+ case "dictionary":
2205
+ case "instance":
2206
+ case "class":
2207
+ case "function": {
2208
+ // every field, now and later
2209
+ const seen = new Set();
2210
+ const copy = () => {
2211
+ for (const [name, id] of this.fields.get(a) ?? new Map()) {
2212
+ if (seen.has(name))
2213
+ continue;
2214
+ seen.add(name);
2215
+ this.edge(id, dst);
2216
+ }
2217
+ };
2218
+ copy();
2219
+ this.lateCopies.push(copy);
2220
+ if (a.kind === "instance" || a.kind === "class")
2221
+ this.add(dst, this.top);
2222
+ return;
2223
+ }
2224
+ default:
2225
+ this.add(dst, this.top);
2226
+ }
2227
+ void site;
2228
+ });
2229
+ }
2230
+ computedStore(recv, value, site) {
2231
+ this.on(recv, (a) => {
2232
+ switch (a.kind) {
2233
+ case "top":
2234
+ this.noteTopWrite(null, site);
2235
+ this.sink(value, `stored into ⊤[k] at ${locLabel(site)}`);
2236
+ return;
2237
+ case "array":
2238
+ // An index, or a named property under an unknown key.
2239
+ this.edge(value, this.element(a));
2240
+ this.edge(value, this.anyField(a));
2241
+ return;
2242
+ case "prim":
2243
+ return;
2244
+ case "object":
2245
+ case "dictionary":
2246
+ case "instance":
2247
+ case "class":
2248
+ case "function":
2249
+ this.edge(value, this.anyField(a));
2250
+ return;
2251
+ default:
2252
+ // As a store under a name: a builtin, promise or collection keeps it where it isn't tracked.
2253
+ this.sink(value, `stored into ${a.label}[k] at ${locLabel(site)}`);
2254
+ }
2255
+ });
2256
+ }
2257
+ // ---- calls ---------------------------------------------------------------------------
2258
+ /** tag`…${x}…`: a call of the tag with the template's strings array (an
2259
+ * array of strings with a `raw` array of strings) and each substitution. */
2260
+ taggedTemplate(e) {
2261
+ this.noteSite(e);
2262
+ const tag = unparen(e.tag);
2263
+ const recv = ts.isPropertyAccessExpression(tag) && tag.expression.kind !== ts.SyntaxKind.SuperKeyword
2264
+ ? this.expr(tag.expression)
2265
+ : null;
2266
+ const callee = recv === null ? this.expr(tag) : null;
2267
+ const strings = this.syntheticArray(e, "template");
2268
+ const raw = this.syntheticArray(e.template, "raw");
2269
+ this.add(this.element(strings), this.prim("string"));
2270
+ this.add(this.element(raw), this.prim("string"));
2271
+ this.add(this.field(strings, "raw"), raw);
2272
+ const args = [this.constNode(strings)];
2273
+ if (ts.isTemplateExpression(e.template))
2274
+ for (const span of list(e.template.templateSpans))
2275
+ args.push(this.expr(span.expression));
2276
+ const dst = this.newNode();
2277
+ if (recv !== null && ts.isPropertyAccessExpression(tag)) {
2278
+ const name = tag.name.text;
2279
+ this.ops.push({ kind: "read", recv, name, node: tag });
2280
+ this.on(recv, (a) => {
2281
+ const fn = this.newNode();
2282
+ this.loadAtom(a, name, fn, tag);
2283
+ this.invoke(fn, this.constNode(a), args, false, dst, e);
2284
+ });
2285
+ }
2286
+ else
2287
+ this.invoke(callee, null, args, false, dst, e);
2288
+ return dst;
2289
+ }
2290
+ args(e) {
2291
+ const out = [];
2292
+ let spread = false;
2293
+ for (const a of list(e.arguments)) {
2294
+ if (ts.isSpreadElement(a)) {
2295
+ const inner = unparen(a.expression);
2296
+ if (ts.isIdentifier(inner) && inner.text === "arguments") {
2297
+ // `f(...arguments)`: forward the enclosing function's parameters.
2298
+ const fn = this.enclosingNonArrow();
2299
+ if (fn !== null && out.length === 0) {
2300
+ if (fn.argPos === null)
2301
+ fn.argPos = [0, 1, 2, 3, 4, 5].map(() => this.newNode());
2302
+ out.push(...fn.argPos);
2303
+ continue;
2304
+ }
2305
+ }
2306
+ spread = true;
2307
+ out.push(this.expr(a.expression));
2308
+ continue;
2309
+ }
2310
+ out.push(this.expr(a));
2311
+ }
2312
+ return { args: out, spread };
2313
+ }
2314
+ call(e) {
2315
+ this.noteSite(e);
2316
+ const callee = unparen(e.expression);
2317
+ const dst = this.newNode();
2318
+ if (callee.kind === ts.SyntaxKind.SuperKeyword) {
2319
+ const { args, spread } = this.args(e);
2320
+ const fn = this.enclosingNonArrow();
2321
+ const owner = fn?.ownerClass ?? null;
2322
+ const base = owner !== null ? this.baseClass(owner) : undefined;
2323
+ if (fn !== null && base) {
2324
+ this.on(fn.thisNode, (inst) => {
2325
+ if (inst.kind === "instance")
2326
+ this.callConstructorChain(base, inst, args, spread, e);
2327
+ });
2328
+ }
2329
+ else if (base === undefined)
2330
+ for (const a of args)
2331
+ this.sink(a, `super(...) at ${locLabel(e)}`);
2332
+ return dst;
2333
+ }
2334
+ // CommonJS `require("<spec>")` of an analyzed module: its exports (the
2335
+ // module's namespace, which holds `module.exports` as its `exports`
2336
+ // field and the checker's view of its exports).
2337
+ if (ts.isIdentifier(callee) && callee.text === "require" && e.arguments.nodes.length === 1) {
2338
+ const spec = e.arguments.nodes[0];
2339
+ if (ts.isStringLiteral(spec)) {
2340
+ let target;
2341
+ try {
2342
+ const sym = this.checker.getSymbolAtLocation(spec);
2343
+ target = sym?.valueDeclaration ?? sym?.declarations[0];
2344
+ }
2345
+ catch {
2346
+ target = undefined;
2347
+ }
2348
+ if (target !== undefined && ts.isSourceFile(target) && this.files.includes(target)) {
2349
+ const ns = this.namespaceNode(target);
2350
+ this.edge(ns, dst);
2351
+ this.on(ns, (a) => this.edge(this.field(a, "exports"), dst));
2352
+ return dst;
2353
+ }
2354
+ }
2355
+ }
2356
+ if (ts.isPropertyAccessExpression(callee) || ts.isElementAccessExpression(callee)) {
2357
+ const recvExpr = unparen(callee.expression);
2358
+ const { args, spread } = this.args(e);
2359
+ if (recvExpr.kind === ts.SyntaxKind.SuperKeyword && ts.isPropertyAccessExpression(callee)) {
2360
+ // super.m(...): the base class member with the current receiver.
2361
+ const fn = this.enclosingNonArrow();
2362
+ const owner = fn?.ownerClass ?? null;
2363
+ const base = owner !== null ? this.baseClass(owner) : undefined;
2364
+ if (fn !== null && base) {
2365
+ const member = this.lookupMember(base, callee.name.text, isStatic(fn.node));
2366
+ if (member?.method !== undefined) {
2367
+ this.callFunction(this.functionInfo(member.method, this.ownerOf(member.method), fn.ctx), fn.thisNode, args, spread, dst, e);
2368
+ }
2369
+ }
2370
+ return dst;
2371
+ }
2372
+ const recv = this.expr(recvExpr);
2373
+ let name = null;
2374
+ if (ts.isPropertyAccessExpression(callee))
2375
+ name = callee.name.text;
2376
+ else {
2377
+ const k = unparen(callee.argumentExpression);
2378
+ if (ts.isStringLiteral(k) || ts.isNoSubstitutionTemplateLiteral(k))
2379
+ name = k.text;
2380
+ else
2381
+ this.expr(callee.argumentExpression);
2382
+ }
2383
+ if (name !== null)
2384
+ this.ops.push({ kind: "read", recv, name, node: callee });
2385
+ // Per receiver atom: the member it resolves to runs with that atom as `this`.
2386
+ const member = name;
2387
+ this.on(recv, (a) => {
2388
+ const fnNode = this.newNode();
2389
+ const self = this.constNode(a);
2390
+ if (member !== null)
2391
+ this.loadAtom(a, member, fnNode, callee);
2392
+ else
2393
+ this.computedLoad(self, fnNode, callee);
2394
+ this.invoke(fnNode, self, args, spread, dst, e);
2395
+ });
2396
+ return dst;
2397
+ }
2398
+ const calleeNode = this.expr(callee);
2399
+ const { args, spread } = this.args(e);
2400
+ this.invoke(calleeNode, null, args, spread, dst, e);
2401
+ return dst;
2402
+ }
2403
+ invoke(callee, recv, args, spread, dst, site) {
2404
+ const undefNode = recv === null ? this.constNode(this.prim("undefined")) : recv;
2405
+ this.on(callee, (a) => {
2406
+ switch (a.kind) {
2407
+ case "function":
2408
+ this.callFunction(this.infoOfAtom(a), undefNode, args, spread, dst, site);
2409
+ return;
2410
+ case "builtin":
2411
+ this.callBuiltin(a, args, spread, dst, site, recv);
2412
+ return;
2413
+ case "class":
2414
+ return; // calling a class throws
2415
+ case "prim":
2416
+ return;
2417
+ default:
2418
+ for (const x of args)
2419
+ this.sink(x, `argument of ⊤ call at ${locLabel(site)}`);
2420
+ if (recv !== null && a.kind === "top")
2421
+ this.sink(recv, `receiver of ⊤ call at ${locLabel(site)}`);
2422
+ this.add(dst, this.top);
2423
+ }
2424
+ });
2425
+ }
2426
+ newExpr(e) {
2427
+ this.noteSite(e);
2428
+ const dst = this.newNode();
2429
+ const callee = this.expr(e.expression);
2430
+ const { args, spread } = this.args(e);
2431
+ this.on(callee, (a) => {
2432
+ switch (a.kind) {
2433
+ case "class":
2434
+ this.construct(a.node, args, spread, dst, e);
2435
+ return;
2436
+ case "function": {
2437
+ // An ES5 constructor function: one instance atom per function.
2438
+ const inst = this.atoms.intern(`fninst:${this.nodeKey(a.node)}`, () => ({
2439
+ kind: "object",
2440
+ label: `new ${a.label}`,
2441
+ node: a.node,
2442
+ }));
2443
+ this.fnOfInstance.set(inst, a);
2444
+ this.add(dst, inst);
2445
+ const info = this.infoOfAtom(a);
2446
+ if (info !== undefined) {
2447
+ this.activate(info);
2448
+ this.add(info.thisNode, inst);
2449
+ this.bindArgs(info, args, spread);
2450
+ this.edge(info.ret, dst);
2451
+ this.edgeFor(e, info);
2452
+ }
2453
+ return;
2454
+ }
2455
+ case "builtin":
2456
+ this.constructBuiltin(a.path ?? "", args, dst, e);
2457
+ return;
2458
+ default:
2459
+ for (const x of args)
2460
+ this.sink(x, `argument of ⊤ constructor at ${locLabel(e)}`);
2461
+ this.add(dst, this.top);
2462
+ }
2463
+ });
2464
+ return dst;
2465
+ }
2466
+ constructBuiltin(path, args, dst, site) {
2467
+ switch (path) {
2468
+ case "Map":
2469
+ case "Set":
2470
+ case "WeakMap":
2471
+ case "WeakSet": {
2472
+ const c = this.atoms.intern(`coll:${this.nodeKey(site)}`, () => ({
2473
+ kind: "collection",
2474
+ label: `${path}@${locLabel(site)}`,
2475
+ node: site,
2476
+ }));
2477
+ this.add(dst, c);
2478
+ if (args[0] !== undefined)
2479
+ this.iterateInto(args[0], this.element(c), site);
2480
+ return;
2481
+ }
2482
+ case "Error":
2483
+ case "TypeError":
2484
+ case "RangeError":
2485
+ case "SyntaxError":
2486
+ this.add(dst, this.builtin("Error.instance"));
2487
+ return;
2488
+ case "Promise": {
2489
+ const p = this.promiseAtom(site, locLabel(site));
2490
+ this.add(this.field(p, "value"), this.top);
2491
+ this.add(dst, p);
2492
+ if (args[0] !== undefined) {
2493
+ const resolver = this.constNode(this.builtin("promise.resolver"));
2494
+ this.on(args[0], (f) => {
2495
+ if (f.kind === "function")
2496
+ this.callFunction(this.infoOfAtom(f), null, [resolver, resolver], false, this.newNode(), site);
2497
+ });
2498
+ }
2499
+ return;
2500
+ }
2501
+ case "Date":
2502
+ this.add(dst, this.builtin("Date.instance"));
2503
+ return;
2504
+ case "RegExp":
2505
+ this.add(dst, this.builtin("RegExp.instance"));
2506
+ return;
2507
+ case "Array": {
2508
+ this.add(dst, this.syntheticArray(site, "Array"));
2509
+ return;
2510
+ }
2511
+ case "Proxy":
2512
+ // The handler's traps run on every operation with the target.
2513
+ if (args[0] !== undefined)
2514
+ this.ops.push({ kind: "proxy", recv: args[0], name: null, node: site });
2515
+ for (const x of args)
2516
+ this.sink(x, `argument of new Proxy at ${locLabel(site)}`);
2517
+ this.add(dst, this.top);
2518
+ return;
2519
+ default:
2520
+ for (const x of args)
2521
+ this.sink(x, `argument of new ${path} at ${locLabel(site)}`);
2522
+ this.add(dst, this.top);
2523
+ }
2524
+ }
2525
+ /** Builtin call summaries; anything unmodeled makes its arguments escape. */
2526
+ callBuiltin(a, args, spread, dst, site, recvNode) {
2527
+ const path = a.path ?? "";
2528
+ const recv = a.receiver;
2529
+ const arg = (i) => args[i] ?? this.constNode(this.prim("undefined"));
2530
+ const prim = (p) => this.add(dst, this.prim(p));
2531
+ const callback = (i, cbArgs, ret) => {
2532
+ if (args[i] === undefined)
2533
+ return;
2534
+ this.on(args[i], (f) => {
2535
+ if (f.kind === "function") {
2536
+ const saved = this.forceLoop;
2537
+ this.forceLoop = LOOP_CALLBACK_METHODS.has(path.slice(path.indexOf(".") + 1));
2538
+ this.callFunction(this.infoOfAtom(f), null, cbArgs, false, ret ?? this.newNode(), site);
2539
+ this.forceLoop = saved;
2540
+ }
2541
+ else if (f.kind === "top" || f.kind === "builtin") {
2542
+ for (const x of cbArgs)
2543
+ this.sink(x, `argument of ⊤ callback at ${locLabel(site)}`);
2544
+ if (ret !== null)
2545
+ this.add(ret, this.top);
2546
+ }
2547
+ });
2548
+ };
2549
+ const escapeAll = () => {
2550
+ for (const x of args)
2551
+ this.sink(x, `argument of ${path} at ${locLabel(site)}`);
2552
+ this.add(dst, this.top);
2553
+ };
2554
+ // Methods of builtin receivers.
2555
+ if (recv !== undefined) {
2556
+ const method = path.slice(path.indexOf(".") + 1);
2557
+ if (path.startsWith("array.")) {
2558
+ const el = this.element(recv);
2559
+ const num = this.constNode(this.prim("number"));
2560
+ const recvN = this.constNode(recv);
2561
+ switch (method) {
2562
+ case "push":
2563
+ case "unshift":
2564
+ for (const x of args) {
2565
+ if (spread)
2566
+ this.iterateInto(x, el, site);
2567
+ else
2568
+ this.edge(x, el);
2569
+ }
2570
+ prim("number");
2571
+ return;
2572
+ case "pop":
2573
+ case "shift":
2574
+ case "at":
2575
+ this.edge(el, dst);
2576
+ this.add(dst, this.prim("undefined"));
2577
+ return;
2578
+ case "find":
2579
+ case "findLast":
2580
+ callback(0, [el, num, recvN], null);
2581
+ this.edge(el, dst);
2582
+ this.add(dst, this.prim("undefined"));
2583
+ return;
2584
+ case "forEach":
2585
+ callback(0, [el, num, recvN], null);
2586
+ prim("undefined");
2587
+ return;
2588
+ case "some":
2589
+ case "every":
2590
+ case "includes":
2591
+ callback(0, [el, num, recvN], null);
2592
+ prim("boolean");
2593
+ return;
2594
+ case "findIndex":
2595
+ case "findLastIndex":
2596
+ case "indexOf":
2597
+ case "lastIndexOf":
2598
+ callback(0, [el, num, recvN], null);
2599
+ prim("number");
2600
+ return;
2601
+ case "join":
2602
+ case "toString":
2603
+ prim("string");
2604
+ return;
2605
+ case "map":
2606
+ case "flatMap": {
2607
+ const out = this.syntheticArray(site, method);
2608
+ const outEl = this.element(out);
2609
+ if (method === "map")
2610
+ callback(0, [el, num, recvN], outEl);
2611
+ else {
2612
+ const r = this.newNode();
2613
+ callback(0, [el, num, recvN], r);
2614
+ this.iterateInto(r, outEl, site);
2615
+ }
2616
+ this.add(dst, out);
2617
+ return;
2618
+ }
2619
+ case "filter":
2620
+ case "slice":
2621
+ case "concat":
2622
+ case "reverse":
2623
+ case "sort":
2624
+ case "splice":
2625
+ case "toSorted":
2626
+ case "toReversed":
2627
+ case "flat": {
2628
+ if (method === "filter")
2629
+ callback(0, [el, num, recvN], null);
2630
+ if (method === "sort" || method === "toSorted")
2631
+ callback(0, [el, el], null);
2632
+ if (method === "reverse" || method === "sort") {
2633
+ this.add(dst, recv);
2634
+ return;
2635
+ }
2636
+ const out = this.syntheticArray(site, method);
2637
+ this.edge(el, this.element(out));
2638
+ if (method === "concat")
2639
+ for (const x of args)
2640
+ this.iterateInto(x, this.element(out), site);
2641
+ if (method === "splice")
2642
+ for (const x of args.slice(2))
2643
+ this.edge(x, el);
2644
+ this.add(dst, out);
2645
+ return;
2646
+ }
2647
+ case "reduce":
2648
+ case "reduceRight": {
2649
+ const acc = this.newNode();
2650
+ if (args[1] !== undefined)
2651
+ this.edge(args[1], acc);
2652
+ else
2653
+ this.edge(el, acc);
2654
+ callback(0, [acc, el, num, recvN], acc);
2655
+ this.edge(acc, dst);
2656
+ return;
2657
+ }
2658
+ case "keys":
2659
+ case "values":
2660
+ case "entries": {
2661
+ const out = this.syntheticArray(site, method);
2662
+ if (method === "values")
2663
+ this.edge(el, this.element(out));
2664
+ else if (method === "keys")
2665
+ this.add(this.element(out), this.prim("number"));
2666
+ else {
2667
+ const pair = this.syntheticArray(site, "entry");
2668
+ this.add(this.element(pair), this.prim("number"));
2669
+ this.edge(el, this.element(pair));
2670
+ this.add(this.element(out), pair);
2671
+ }
2672
+ this.add(dst, out);
2673
+ return;
2674
+ }
2675
+ case "fill":
2676
+ for (const x of args)
2677
+ this.edge(x, el);
2678
+ this.add(dst, recv);
2679
+ return;
2680
+ }
2681
+ escapeAll();
2682
+ this.escape(recv, `array.${method} at ${locLabel(site)}`);
2683
+ return;
2684
+ }
2685
+ if (path.startsWith("string.") || path.startsWith("number.") || path.startsWith("boolean.")) {
2686
+ const r = STRING_METHOD_RESULTS.get(method);
2687
+ if (r === "array") {
2688
+ const out = this.syntheticArray(site, method);
2689
+ this.add(this.element(out), this.prim("string"));
2690
+ this.add(this.element(out), this.prim("undefined"));
2691
+ this.add(dst, out);
2692
+ this.add(dst, this.prim("null"));
2693
+ }
2694
+ else if (r !== undefined)
2695
+ prim(r);
2696
+ else if (method === "replace" || method === "replaceAll")
2697
+ prim("string");
2698
+ else
2699
+ escapeAll();
2700
+ if (method === "replace" || method === "replaceAll")
2701
+ callback(1, [this.constNode(this.prim("string"))], null);
2702
+ return;
2703
+ }
2704
+ if (path.startsWith("regexp.")) {
2705
+ if (method === "test")
2706
+ prim("boolean");
2707
+ else if (method === "exec") {
2708
+ const out = this.syntheticArray(site, "exec");
2709
+ this.add(this.element(out), this.prim("string"));
2710
+ this.add(dst, out);
2711
+ prim("null");
2712
+ }
2713
+ else
2714
+ escapeAll();
2715
+ return;
2716
+ }
2717
+ if (path.startsWith("promise.")) {
2718
+ const out = this.promiseAtom(site, locLabel(site));
2719
+ const value = this.field(recv, "value");
2720
+ const ret = this.newNode();
2721
+ if (method === "then") {
2722
+ callback(0, [value], ret);
2723
+ callback(1, [this.constNode(this.top)], ret);
2724
+ }
2725
+ else if (method === "catch") {
2726
+ callback(0, [this.constNode(this.top)], ret);
2727
+ this.edge(value, ret);
2728
+ }
2729
+ else {
2730
+ callback(0, [], null);
2731
+ this.edge(value, ret);
2732
+ }
2733
+ this.awaitInto(ret, this.field(out, "value"));
2734
+ this.add(dst, out);
2735
+ return;
2736
+ }
2737
+ if (path.startsWith("collection.")) {
2738
+ const el = this.element(recv);
2739
+ switch (method) {
2740
+ case "add":
2741
+ case "set":
2742
+ for (const x of args)
2743
+ this.edge(x, el);
2744
+ this.add(dst, recv);
2745
+ return;
2746
+ case "get":
2747
+ this.edge(el, dst);
2748
+ prim("undefined");
2749
+ return;
2750
+ case "has":
2751
+ case "delete":
2752
+ prim("boolean");
2753
+ return;
2754
+ case "clear":
2755
+ prim("undefined");
2756
+ return;
2757
+ case "forEach":
2758
+ callback(0, [el, el], null);
2759
+ prim("undefined");
2760
+ return;
2761
+ case "keys":
2762
+ case "values":
2763
+ case "entries": {
2764
+ const out = this.syntheticArray(site, method);
2765
+ this.edge(el, this.element(out));
2766
+ if (method === "entries") {
2767
+ const pair = this.syntheticArray(site, "entry");
2768
+ this.edge(el, this.element(pair));
2769
+ this.nodes[this.element(out)].atoms.clear();
2770
+ this.add(this.element(out), pair);
2771
+ }
2772
+ this.add(dst, out);
2773
+ return;
2774
+ }
2775
+ }
2776
+ escapeAll();
2777
+ return;
2778
+ }
2779
+ if (path.startsWith("function.")) {
2780
+ if (recv.kind !== "function" || recv.node === undefined) {
2781
+ escapeAll();
2782
+ return;
2783
+ }
2784
+ if (method === "bind") {
2785
+ const info = this.infoOfAtom(recv);
2786
+ if (info !== undefined && args[0] !== undefined && !info.isArrow)
2787
+ this.edge(args[0], info.thisNode);
2788
+ if (info !== undefined && args.length > 1) {
2789
+ this.activate(info);
2790
+ for (const p of info.params)
2791
+ this.add(p, this.top);
2792
+ for (const x of args.slice(1))
2793
+ this.sink(x, `bound argument at ${locLabel(site)}`);
2794
+ }
2795
+ this.add(dst, recv);
2796
+ return;
2797
+ }
2798
+ if (method === "call") {
2799
+ this.callFunction(this.infoOfAtom(recv), args[0] ?? this.constNode(this.prim("undefined")), args.slice(1), spread, dst, site);
2800
+ return;
2801
+ }
2802
+ // apply: arguments from an array
2803
+ const info = this.infoOfAtom(recv);
2804
+ if (info !== undefined) {
2805
+ this.activate(info);
2806
+ if (args[0] !== undefined && !info.isArrow)
2807
+ this.edge(args[0], info.thisNode);
2808
+ for (const p of info.params)
2809
+ if (args[1] !== undefined)
2810
+ this.iterateInto(args[1], p, site);
2811
+ this.edge(info.ret, dst);
2812
+ this.edgeFor(site, info);
2813
+ }
2814
+ return;
2815
+ }
2816
+ if (path.startsWith("object.")) {
2817
+ if (method === "hasOwnProperty")
2818
+ prim("boolean");
2819
+ else if (method === "toString")
2820
+ prim("string");
2821
+ else
2822
+ escapeAll();
2823
+ return;
2824
+ }
2825
+ escapeAll();
2826
+ return;
2827
+ }
2828
+ // `Object.prototype.m.call(o, …)`-style calls of builtin prototype methods.
2829
+ if (/^(Object|Array|String|Function)\.prototype\.\w+\.(call|apply)$/.test(path)) {
2830
+ const m = path.split(".")[2];
2831
+ if (m === "hasOwnProperty" || m === "propertyIsEnumerable" || m === "isPrototypeOf")
2832
+ prim("boolean");
2833
+ else if (m === "toString")
2834
+ prim("string");
2835
+ else
2836
+ escapeAll();
2837
+ return;
2838
+ }
2839
+ switch (path) {
2840
+ case "Object.keys":
2841
+ case "Object.getOwnPropertyNames": {
2842
+ const out = this.syntheticArray(site, "keys");
2843
+ this.add(this.element(out), this.prim("string"));
2844
+ this.add(dst, out);
2845
+ return;
2846
+ }
2847
+ case "Object.values":
2848
+ case "Object.entries": {
2849
+ const out = this.syntheticArray(site, path === "Object.values" ? "values" : "entries");
2850
+ const vals = this.newNode();
2851
+ if (args[0] !== undefined)
2852
+ this.computedLoad(args[0], vals, site);
2853
+ if (path === "Object.values")
2854
+ this.edge(vals, this.element(out));
2855
+ else {
2856
+ const pair = this.syntheticArray(site, "entry");
2857
+ this.add(this.element(pair), this.prim("string"));
2858
+ this.edge(vals, this.element(pair));
2859
+ this.add(this.element(out), pair);
2860
+ }
2861
+ this.add(dst, out);
2862
+ return;
2863
+ }
2864
+ case "Object.freeze":
2865
+ case "Object.seal":
2866
+ case "Object.preventExtensions":
2867
+ this.ops.push({
2868
+ kind: path === "Object.freeze" ? "freeze" : "seal",
2869
+ recv: arg(0),
2870
+ name: null,
2871
+ node: site,
2872
+ });
2873
+ this.edge(arg(0), dst);
2874
+ return;
2875
+ case "Object.isFrozen":
2876
+ case "Object.isSealed":
2877
+ case "Object.isExtensible":
2878
+ case "Array.isArray":
2879
+ case "Number.isInteger":
2880
+ case "Number.isNaN":
2881
+ case "Number.isFinite":
2882
+ case "Number.isSafeInteger":
2883
+ case "isNaN":
2884
+ case "isFinite":
2885
+ prim("boolean");
2886
+ return;
2887
+ case "Object.assign": {
2888
+ this.ops.push({ kind: "assign", recv: arg(0), name: null, node: site });
2889
+ this.on(arg(0), (t) => {
2890
+ for (const s of args.slice(1))
2891
+ this.copyFields(s, t, site);
2892
+ if (t.kind === "top")
2893
+ for (const s of args.slice(1))
2894
+ this.sink(s, `Object.assign into ⊤ at ${locLabel(site)}`);
2895
+ });
2896
+ this.edge(arg(0), dst);
2897
+ return;
2898
+ }
2899
+ case "Object.defineProperty":
2900
+ case "Object.defineProperties":
2901
+ case "Reflect.defineProperty":
2902
+ this.ops.push({ kind: "defineProperty", recv: arg(0), name: null, node: site });
2903
+ this.sink(arg(2), `property descriptor at ${locLabel(site)}`);
2904
+ this.sink(arg(1), `property descriptor at ${locLabel(site)}`);
2905
+ this.edge(arg(0), dst);
2906
+ return;
2907
+ case "Object.setPrototypeOf":
2908
+ case "Reflect.setPrototypeOf":
2909
+ this.ops.push({ kind: "setPrototypeOf", recv: arg(0), name: null, node: site });
2910
+ this.sink(arg(1), `prototype at ${locLabel(site)}`);
2911
+ this.edge(arg(0), dst);
2912
+ return;
2913
+ case "Object.create": {
2914
+ const d = this.atoms.intern(`dict:${this.nodeKey(site)}`, () => ({
2915
+ kind: "dictionary",
2916
+ label: `Object.create@${locLabel(site)}`,
2917
+ node: site,
2918
+ }));
2919
+ this.add(dst, d);
2920
+ return;
2921
+ }
2922
+ case "Object.fromEntries": {
2923
+ const d = this.atoms.intern(`dict:${this.nodeKey(site)}`, () => ({
2924
+ kind: "dictionary",
2925
+ label: `fromEntries@${locLabel(site)}`,
2926
+ node: site,
2927
+ }));
2928
+ const pairs = this.newNode();
2929
+ if (args[0] !== undefined)
2930
+ this.iterateInto(args[0], pairs, site);
2931
+ const vals = this.newNode();
2932
+ this.iterateInto(pairs, vals, site);
2933
+ this.edge(vals, this.anyField(d));
2934
+ this.add(dst, d);
2935
+ return;
2936
+ }
2937
+ case "Object.getPrototypeOf":
2938
+ case "Reflect.getPrototypeOf":
2939
+ this.add(dst, this.top);
2940
+ return;
2941
+ case "Object.is":
2942
+ prim("boolean");
2943
+ return;
2944
+ case "Array.from":
2945
+ case "Array.of": {
2946
+ const out = this.syntheticArray(site, path);
2947
+ if (path === "Array.of")
2948
+ for (const x of args)
2949
+ this.edge(x, this.element(out));
2950
+ else if (args[1] !== undefined) {
2951
+ const els = this.newNode();
2952
+ if (args[0] !== undefined)
2953
+ this.iterateInto(args[0], els, site);
2954
+ callback(1, [els, this.constNode(this.prim("number"))], this.element(out));
2955
+ }
2956
+ else if (args[0] !== undefined)
2957
+ this.iterateInto(args[0], this.element(out), site);
2958
+ this.add(dst, out);
2959
+ return;
2960
+ }
2961
+ case "JSON.parse": {
2962
+ // A reviver runs on every parsed value with its key, the holder as `this`, innermost first:
2963
+ // what it returns replaces the value, in its holder (which later calls receive) and in the
2964
+ // result.
2965
+ const revived = this.newNode();
2966
+ this.add(revived, this.top);
2967
+ this.repeatingSites.add(site);
2968
+ if (args[1] !== undefined)
2969
+ this.on(args[1], (f) => {
2970
+ if (f.kind === "function")
2971
+ this.callFunction(this.infoOfAtom(f), revived, [this.constNode(this.prim("string")), revived], false, revived, site);
2972
+ else if (f.kind === "top")
2973
+ this.sink(revived, `JSON.parse reviver at ${locLabel(site)}`);
2974
+ });
2975
+ this.edge(revived, dst);
2976
+ return;
2977
+ }
2978
+ case "JSON.stringify": {
2979
+ // Every value it serializes: toJSON methods run on them, and a
2980
+ // replacer function with each key and value, the holder as `this`.
2981
+ // Their results are serialized in turn.
2982
+ const serialized = this.newNode();
2983
+ this.childrenInto(serialized);
2984
+ this.repeatingSites.add(site);
2985
+ this.edge(arg(0), serialized);
2986
+ const key = this.constNode(this.prim("string"));
2987
+ this.on(serialized, (v) => this.callToJSON(v, key, serialized, site));
2988
+ if (args[1] !== undefined)
2989
+ this.on(args[1], (f) => {
2990
+ if (f.kind === "function")
2991
+ this.callFunction(this.infoOfAtom(f), serialized, [key, serialized], false, serialized, site);
2992
+ else if (f.kind === "top")
2993
+ this.sink(serialized, `JSON.stringify replacer at ${locLabel(site)}`);
2994
+ });
2995
+ prim("string");
2996
+ prim("undefined");
2997
+ return;
2998
+ }
2999
+ case "Reflect.deleteProperty": {
3000
+ const key = ts.isCallExpression(site) ? unparen(list(site.arguments)[1]) : undefined;
3001
+ const name = key !== undefined && (ts.isStringLiteral(key) || ts.isNoSubstitutionTemplateLiteral(key))
3002
+ ? key.text
3003
+ : null;
3004
+ this.ops.push({ kind: "delete", recv: arg(0), name, node: site });
3005
+ prim("boolean");
3006
+ return;
3007
+ }
3008
+ case "Proxy.revocable":
3009
+ this.ops.push({ kind: "proxy", recv: arg(0), name: null, node: site });
3010
+ escapeAll();
3011
+ return;
3012
+ case "Reflect.construct": {
3013
+ // Reflect.construct(Proxy, [target, handler]) is `new Proxy(target, handler)`: the arguments
3014
+ // are the list's elements.
3015
+ const listed = this.newNode();
3016
+ if (args[1] !== undefined)
3017
+ this.iterateInto(args[1], listed, site);
3018
+ this.on(arg(0), (c) => {
3019
+ if (c.kind === "builtin" && c.path === "Proxy")
3020
+ this.ops.push({ kind: "proxy", recv: listed, name: null, node: site });
3021
+ });
3022
+ this.sink(listed, `argument of ${path} at ${locLabel(site)}`);
3023
+ escapeAll();
3024
+ return;
3025
+ }
3026
+ case "String":
3027
+ case "encodeURIComponent":
3028
+ case "decodeURIComponent":
3029
+ case "encodeURI":
3030
+ case "decodeURI":
3031
+ prim("string");
3032
+ return;
3033
+ case "Number":
3034
+ case "parseInt":
3035
+ case "parseFloat":
3036
+ case "Number.parseInt":
3037
+ case "Number.parseFloat":
3038
+ prim("number");
3039
+ return;
3040
+ case "Boolean":
3041
+ prim("boolean");
3042
+ return;
3043
+ case "Symbol":
3044
+ case "Symbol.for":
3045
+ prim("symbol");
3046
+ return;
3047
+ case "BigInt":
3048
+ prim("bigint");
3049
+ return;
3050
+ case "Promise.resolve": {
3051
+ const p = this.promiseAtom(site, locLabel(site));
3052
+ if (args[0] !== undefined)
3053
+ this.awaitInto(args[0], this.field(p, "value"));
3054
+ else
3055
+ this.add(this.field(p, "value"), this.prim("undefined"));
3056
+ this.add(dst, p);
3057
+ return;
3058
+ }
3059
+ case "Promise.reject": {
3060
+ const p = this.promiseAtom(site, locLabel(site));
3061
+ this.add(dst, p);
3062
+ if (args[0] !== undefined)
3063
+ this.sink(args[0], `rejection at ${locLabel(site)}`);
3064
+ return;
3065
+ }
3066
+ case "Promise.all":
3067
+ case "Promise.allSettled":
3068
+ case "Promise.race":
3069
+ case "Promise.any": {
3070
+ const p = this.promiseAtom(site, locLabel(site));
3071
+ const items = this.newNode();
3072
+ if (args[0] !== undefined)
3073
+ this.iterateInto(args[0], items, site);
3074
+ if (path === "Promise.all") {
3075
+ const out = this.syntheticArray(site, "all");
3076
+ this.awaitInto(items, this.element(out));
3077
+ this.add(this.field(p, "value"), out);
3078
+ }
3079
+ else if (path === "Promise.race" || path === "Promise.any")
3080
+ this.awaitInto(items, this.field(p, "value"));
3081
+ else
3082
+ this.add(this.field(p, "value"), this.top);
3083
+ this.add(dst, p);
3084
+ return;
3085
+ }
3086
+ case "promise.resolver":
3087
+ for (const x of args)
3088
+ this.sink(x, `promise resolution at ${locLabel(site)}`);
3089
+ return;
3090
+ }
3091
+ if (path.startsWith("console.")) {
3092
+ prim("undefined");
3093
+ return;
3094
+ }
3095
+ if (path.startsWith("Math.")) {
3096
+ prim("number");
3097
+ return;
3098
+ }
3099
+ if (path === "Date.now") {
3100
+ prim("number");
3101
+ return;
3102
+ }
3103
+ if (path.startsWith("Date.instance") || path === "Error.instance") {
3104
+ escapeAll();
3105
+ return;
3106
+ }
3107
+ void recvNode;
3108
+ escapeAll();
3109
+ }
3110
+ /** Re-run deferred field copies until nothing new flows. */
3111
+ finish() {
3112
+ for (;;) {
3113
+ const before = this.steps;
3114
+ for (const c of this.lateCopies)
3115
+ c();
3116
+ this.solve();
3117
+ if (this.steps === before || this.budgetExceeded)
3118
+ return;
3119
+ }
3120
+ }
3121
+ }
3122
+ /** The export name of a CommonJS export declaration the checker resolves
3123
+ * bindings to: a member of the `module.exports` literal, or the target of
3124
+ * `exports.name =` / `module.exports.name =`. */
3125
+ function cjsExportName(decl) {
3126
+ if (ts.isShorthandPropertyAssignment(decl) || ts.isPropertyAssignment(decl)) {
3127
+ const n = decl.name;
3128
+ return ts.isIdentifier(n) || ts.isStringLiteral(n) ? n.text : null;
3129
+ }
3130
+ if (ts.isPropertyAccessExpression(decl) && ts.isIdentifier(decl.name))
3131
+ return decl.name.text;
3132
+ if (ts.isBinaryExpression(decl) &&
3133
+ ts.isPropertyAccessExpression(decl.left) &&
3134
+ ts.isIdentifier(decl.left.name))
3135
+ return decl.left.name.text;
3136
+ return null;
3137
+ }
3138
+ //# sourceMappingURL=analyze.js.map