@scriptc/compiler 0.3.4 → 0.3.6

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 (316) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +409 -42
  2. package/dist/backend/llvm/array-search.js +1 -1
  3. package/dist/backend/llvm/array-search.js.map +1 -1
  4. package/dist/backend/llvm/call-lifetimes.d.ts +6 -0
  5. package/dist/backend/llvm/call-lifetimes.js +19 -0
  6. package/dist/backend/llvm/call-lifetimes.js.map +1 -1
  7. package/dist/backend/llvm/constant-callbacks.d.ts +2 -21
  8. package/dist/backend/llvm/constant-callbacks.js +36 -219
  9. package/dist/backend/llvm/constant-callbacks.js.map +1 -1
  10. package/dist/backend/llvm/constant-callbacks.test.js +22 -0
  11. package/dist/backend/llvm/constant-callbacks.test.js.map +1 -1
  12. package/dist/backend/llvm/dense-array-access.d.ts +9 -0
  13. package/dist/backend/llvm/dense-array-access.js +27 -1
  14. package/dist/backend/llvm/dense-array-access.js.map +1 -1
  15. package/dist/backend/llvm/dyn.d.ts +6 -0
  16. package/dist/backend/llvm/dyn.js +71 -7
  17. package/dist/backend/llvm/dyn.js.map +1 -1
  18. package/dist/backend/llvm/emitter.d.ts +120 -2
  19. package/dist/backend/llvm/emitter.js +820 -142
  20. package/dist/backend/llvm/emitter.js.map +1 -1
  21. package/dist/backend/llvm/expr-async.js +17 -7
  22. package/dist/backend/llvm/expr-async.js.map +1 -1
  23. package/dist/backend/llvm/expr-bytes.js +1 -1
  24. package/dist/backend/llvm/expr-callbacks.d.ts +11 -0
  25. package/dist/backend/llvm/expr-callbacks.js +53 -0
  26. package/dist/backend/llvm/expr-callbacks.js.map +1 -1
  27. package/dist/backend/llvm/expr-calls.js +88 -2
  28. package/dist/backend/llvm/expr-calls.js.map +1 -1
  29. package/dist/backend/llvm/expr-containers.js +50 -27
  30. package/dist/backend/llvm/expr-containers.js.map +1 -1
  31. package/dist/backend/llvm/expr-dispatch.js +1 -0
  32. package/dist/backend/llvm/expr-dispatch.js.map +1 -1
  33. package/dist/backend/llvm/expr-dynamic.js +25 -1
  34. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  35. package/dist/backend/llvm/expr-primitives.d.ts +1 -1
  36. package/dist/backend/llvm/expr-primitives.js +20 -1
  37. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  38. package/dist/backend/llvm/expr-stream-bridges.js +4 -0
  39. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  40. package/dist/backend/llvm/integer-clones.d.ts +103 -0
  41. package/dist/backend/llvm/integer-clones.js +1336 -0
  42. package/dist/backend/llvm/integer-clones.js.map +1 -0
  43. package/dist/backend/llvm/integer-clones.test.d.ts +1 -0
  44. package/dist/backend/llvm/integer-clones.test.js +219 -0
  45. package/dist/backend/llvm/integer-clones.test.js.map +1 -0
  46. package/dist/backend/llvm/lib-datagram.js +14 -0
  47. package/dist/backend/llvm/lib-datagram.js.map +1 -1
  48. package/dist/backend/llvm/lib-dispatch.js +32 -1
  49. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  50. package/dist/backend/llvm/lib-filesystem.js +61 -1
  51. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  52. package/dist/backend/llvm/lib-network.js +21 -3
  53. package/dist/backend/llvm/lib-network.js.map +1 -1
  54. package/dist/backend/llvm/lib-process.js +34 -0
  55. package/dist/backend/llvm/lib-process.js.map +1 -1
  56. package/dist/backend/llvm/lib-shared.js +77 -2
  57. package/dist/backend/llvm/lib-shared.js.map +1 -1
  58. package/dist/backend/llvm/lib-test.js +16 -3
  59. package/dist/backend/llvm/lib-test.js.map +1 -1
  60. package/dist/backend/llvm/lib-tls.js +6 -0
  61. package/dist/backend/llvm/lib-tls.js.map +1 -1
  62. package/dist/backend/llvm/local-array-reads.js +1 -1
  63. package/dist/backend/llvm/local-array-reads.js.map +1 -1
  64. package/dist/backend/llvm/map-entry-fusion.d.ts +28 -0
  65. package/dist/backend/llvm/map-entry-fusion.js +233 -0
  66. package/dist/backend/llvm/map-entry-fusion.js.map +1 -0
  67. package/dist/backend/llvm/map-entry-fusion.test.d.ts +1 -0
  68. package/dist/backend/llvm/map-entry-fusion.test.js +183 -0
  69. package/dist/backend/llvm/map-entry-fusion.test.js.map +1 -0
  70. package/dist/backend/llvm/map-number-lookup.d.ts +2 -0
  71. package/dist/backend/llvm/map-number-lookup.js +1 -1
  72. package/dist/backend/llvm/map-number-lookup.js.map +1 -1
  73. package/dist/backend/llvm/map-number-lookup.test.js +10 -11
  74. package/dist/backend/llvm/map-number-lookup.test.js.map +1 -1
  75. package/dist/backend/llvm/map-read-lifetimes.d.ts +2 -0
  76. package/dist/backend/llvm/map-read-lifetimes.js +3 -0
  77. package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
  78. package/dist/backend/llvm/map-read-lifetimes.test.js +2 -2
  79. package/dist/backend/llvm/nullable-unions.d.ts +6 -3
  80. package/dist/backend/llvm/nullable-unions.js +2 -0
  81. package/dist/backend/llvm/nullable-unions.js.map +1 -1
  82. package/dist/backend/llvm/publish.d.ts +16 -0
  83. package/dist/backend/llvm/publish.js +81 -10
  84. package/dist/backend/llvm/publish.js.map +1 -1
  85. package/dist/backend/llvm/publish.test.d.ts +1 -0
  86. package/dist/backend/llvm/publish.test.js +94 -0
  87. package/dist/backend/llvm/publish.test.js.map +1 -0
  88. package/dist/backend/llvm/record-results.d.ts +1 -1
  89. package/dist/backend/llvm/record-results.js +78 -4
  90. package/dist/backend/llvm/record-results.js.map +1 -1
  91. package/dist/backend/llvm/record-sources.d.ts +7 -0
  92. package/dist/backend/llvm/record-sources.js +14 -0
  93. package/dist/backend/llvm/record-sources.js.map +1 -0
  94. package/dist/backend/llvm/reference-writes.js +1 -0
  95. package/dist/backend/llvm/reference-writes.js.map +1 -1
  96. package/dist/backend/llvm/shapes.d.ts +12 -3
  97. package/dist/backend/llvm/shapes.js +23 -14
  98. package/dist/backend/llvm/shapes.js.map +1 -1
  99. package/dist/backend/llvm/shapes.test.js +5 -3
  100. package/dist/backend/llvm/shapes.test.js.map +1 -1
  101. package/dist/backend/llvm/speculative-integers.d.ts +74 -0
  102. package/dist/backend/llvm/speculative-integers.js +571 -0
  103. package/dist/backend/llvm/speculative-integers.js.map +1 -0
  104. package/dist/backend/llvm/speculative-integers.test.d.ts +1 -0
  105. package/dist/backend/llvm/speculative-integers.test.js +148 -0
  106. package/dist/backend/llvm/speculative-integers.test.js.map +1 -0
  107. package/dist/backend/llvm/string-lifetimes.test.js +75 -1
  108. package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
  109. package/dist/backend/llvm/walkers.d.ts +17 -0
  110. package/dist/backend/llvm/walkers.js +123 -0
  111. package/dist/backend/llvm/walkers.js.map +1 -1
  112. package/dist/backend/may-throw.js +2 -0
  113. package/dist/backend/may-throw.js.map +1 -1
  114. package/dist/backend/native/contracts.d.ts +2 -1
  115. package/dist/backend/native/executable.js +6 -1
  116. package/dist/backend/native/executable.js.map +1 -1
  117. package/dist/backend/native/runtime-inputs.d.ts +1 -1
  118. package/dist/backend/native/runtime-inputs.js +1 -0
  119. package/dist/backend/native/runtime-inputs.js.map +1 -1
  120. package/dist/backend/runtime-abi.d.ts +2 -2
  121. package/dist/backend/runtime-abi.js +2 -2
  122. package/dist/backend/runtime-pack-targets.test.js +1 -1
  123. package/dist/backend/runtime-pack.d.ts +7 -3
  124. package/dist/backend/runtime-pack.js +12 -6
  125. package/dist/backend/runtime-pack.js.map +1 -1
  126. package/dist/backend/runtime-pack.test.js +16 -7
  127. package/dist/backend/runtime-pack.test.js.map +1 -1
  128. package/dist/contracts/check.js +1 -0
  129. package/dist/contracts/check.js.map +1 -1
  130. package/dist/coverage/surface-manifest.js +3 -3
  131. package/dist/coverage/surface-manifest.js.map +1 -1
  132. package/dist/diagnostics/diagnostic.d.ts +1 -1
  133. package/dist/diagnostics/diagnostic.js +6 -2
  134. package/dist/diagnostics/diagnostic.js.map +1 -1
  135. package/dist/frontend/lowering/builtin-calls.js +13 -0
  136. package/dist/frontend/lowering/builtin-calls.js.map +1 -1
  137. package/dist/frontend/lowering/builtins/callable-aliases.js +82 -8
  138. package/dist/frontend/lowering/builtins/callable-aliases.js.map +1 -1
  139. package/dist/frontend/lowering/builtins/child-process-async.d.ts +8 -6
  140. package/dist/frontend/lowering/builtins/child-process-async.js +45 -29
  141. package/dist/frontend/lowering/builtins/child-process-async.js.map +1 -1
  142. package/dist/frontend/lowering/builtins/compression.d.ts +9 -0
  143. package/dist/frontend/lowering/builtins/compression.js +145 -30
  144. package/dist/frontend/lowering/builtins/compression.js.map +1 -1
  145. package/dist/frontend/lowering/builtins/crypto.js +12 -1
  146. package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
  147. package/dist/frontend/lowering/builtins/errors.js +5 -3
  148. package/dist/frontend/lowering/builtins/errors.js.map +1 -1
  149. package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +6 -0
  150. package/dist/frontend/lowering/builtins/filesystem-calls.js +16 -0
  151. package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
  152. package/dist/frontend/lowering/builtins/filesystem.d.ts +8 -0
  153. package/dist/frontend/lowering/builtins/filesystem.js +199 -2
  154. package/dist/frontend/lowering/builtins/filesystem.js.map +1 -1
  155. package/dist/frontend/lowering/builtins/fs-streams.d.ts +26 -0
  156. package/dist/frontend/lowering/builtins/fs-streams.js +131 -0
  157. package/dist/frontend/lowering/builtins/fs-streams.js.map +1 -0
  158. package/dist/frontend/lowering/builtins/hash-stream.d.ts +12 -0
  159. package/dist/frontend/lowering/builtins/hash-stream.js +80 -0
  160. package/dist/frontend/lowering/builtins/hash-stream.js.map +1 -0
  161. package/dist/frontend/lowering/builtins/module-calls.js +17 -3
  162. package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
  163. package/dist/frontend/lowering/builtins/process.js +9 -2
  164. package/dist/frontend/lowering/builtins/process.js.map +1 -1
  165. package/dist/frontend/lowering/builtins/readline.d.ts +45 -13
  166. package/dist/frontend/lowering/builtins/readline.js +812 -47
  167. package/dist/frontend/lowering/builtins/readline.js.map +1 -1
  168. package/dist/frontend/lowering/builtins/workers.d.ts +4 -0
  169. package/dist/frontend/lowering/builtins/workers.js +58 -0
  170. package/dist/frontend/lowering/builtins/workers.js.map +1 -1
  171. package/dist/frontend/lowering/class-dynamic-dispatch.js +150 -8
  172. package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
  173. package/dist/frontend/lowering/class-protocols.d.ts +55 -0
  174. package/dist/frontend/lowering/class-protocols.js +735 -0
  175. package/dist/frontend/lowering/class-protocols.js.map +1 -1
  176. package/dist/frontend/lowering/containers/array-from-async.d.ts +18 -0
  177. package/dist/frontend/lowering/containers/array-from-async.js +282 -0
  178. package/dist/frontend/lowering/containers/array-from-async.js.map +1 -0
  179. package/dist/frontend/lowering/containers/bytes.js +33 -12
  180. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  181. package/dist/frontend/lowering/containers/collection-grouping.js +2 -1
  182. package/dist/frontend/lowering/containers/collection-grouping.js.map +1 -1
  183. package/dist/frontend/lowering/containers/collection-methods.js +27 -23
  184. package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
  185. package/dist/frontend/lowering/devirtualize.js +20 -7
  186. package/dist/frontend/lowering/devirtualize.js.map +1 -1
  187. package/dist/frontend/lowering/divergences.js +188 -15
  188. package/dist/frontend/lowering/divergences.js.map +1 -1
  189. package/dist/frontend/lowering/lower-calls.js +129 -25
  190. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  191. package/dist/frontend/lowering/lower-classes.js +46 -1
  192. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  193. package/dist/frontend/lowering/lower-dgram.js +55 -15
  194. package/dist/frontend/lowering/lower-dgram.js.map +1 -1
  195. package/dist/frontend/lowering/lower-event-emitter.d.ts +9 -1
  196. package/dist/frontend/lowering/lower-event-emitter.js +88 -1
  197. package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
  198. package/dist/frontend/lowering/lower-exprs.d.ts +4 -0
  199. package/dist/frontend/lowering/lower-exprs.js +239 -71
  200. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  201. package/dist/frontend/lowering/lower-inspect.js +49 -3
  202. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  203. package/dist/frontend/lowering/lower-mock.d.ts +11 -1
  204. package/dist/frontend/lowering/lower-mock.js +377 -61
  205. package/dist/frontend/lowering/lower-mock.js.map +1 -1
  206. package/dist/frontend/lowering/lower-modules.js +1 -0
  207. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  208. package/dist/frontend/lowering/lower-server.d.ts +2 -1
  209. package/dist/frontend/lowering/lower-server.js +234 -21
  210. package/dist/frontend/lowering/lower-server.js.map +1 -1
  211. package/dist/frontend/lowering/lower-stmts.js +60 -13
  212. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  213. package/dist/frontend/lowering/lower-stream.d.ts +1 -3
  214. package/dist/frontend/lowering/lower-stream.js +325 -20
  215. package/dist/frontend/lowering/lower-stream.js.map +1 -1
  216. package/dist/frontend/lowering/lower-test.js +147 -48
  217. package/dist/frontend/lowering/lower-test.js.map +1 -1
  218. package/dist/frontend/lowering/lowerer.d.ts +13 -1
  219. package/dist/frontend/lowering/lowerer.js +10 -2
  220. package/dist/frontend/lowering/lowerer.js.map +1 -1
  221. package/dist/frontend/lowering/null-prototype.d.ts +13 -0
  222. package/dist/frontend/lowering/null-prototype.js +33 -0
  223. package/dist/frontend/lowering/null-prototype.js.map +1 -0
  224. package/dist/frontend/lowering/record-sources.d.ts +15 -0
  225. package/dist/frontend/lowering/record-sources.js +46 -0
  226. package/dist/frontend/lowering/record-sources.js.map +1 -0
  227. package/dist/frontend/lowering/surfaces.d.ts +3 -3
  228. package/dist/frontend/lowering/surfaces.js +59 -5
  229. package/dist/frontend/lowering/surfaces.js.map +1 -1
  230. package/dist/frontend/mock-shapes.d.ts +5 -0
  231. package/dist/frontend/mock-shapes.js +27 -2
  232. package/dist/frontend/mock-shapes.js.map +1 -1
  233. package/dist/frontend/program.js +5 -4
  234. package/dist/frontend/program.js.map +1 -1
  235. package/dist/frontend/type-mapper.d.ts +3 -0
  236. package/dist/frontend/type-mapper.js +148 -4
  237. package/dist/frontend/type-mapper.js.map +1 -1
  238. package/dist/index.js +18 -8
  239. package/dist/index.js.map +1 -1
  240. package/dist/ir/analysis.d.ts +10 -0
  241. package/dist/ir/analysis.js +35 -0
  242. package/dist/ir/analysis.js.map +1 -1
  243. package/dist/ir/analysis.test.js +69 -1
  244. package/dist/ir/analysis.test.js.map +1 -1
  245. package/dist/ir/builtin-effects.js +72 -0
  246. package/dist/ir/builtin-effects.js.map +1 -1
  247. package/dist/ir/builtin-signatures.d.ts +1 -1
  248. package/dist/ir/builtin-signatures.js +258 -13
  249. package/dist/ir/builtin-signatures.js.map +1 -1
  250. package/dist/ir/capture-values.d.ts +107 -0
  251. package/dist/ir/capture-values.js +850 -0
  252. package/dist/ir/capture-values.js.map +1 -0
  253. package/dist/ir/capture-values.test.d.ts +1 -0
  254. package/dist/ir/capture-values.test.js +268 -0
  255. package/dist/ir/capture-values.test.js.map +1 -0
  256. package/dist/ir/field-values.d.ts +16 -0
  257. package/dist/ir/field-values.js +128 -0
  258. package/dist/ir/field-values.js.map +1 -0
  259. package/dist/ir/field-values.test.d.ts +1 -0
  260. package/dist/ir/field-values.test.js +160 -0
  261. package/dist/ir/field-values.test.js.map +1 -0
  262. package/dist/ir/final-fields.d.ts +4 -1
  263. package/dist/ir/final-fields.js +11 -3
  264. package/dist/ir/final-fields.js.map +1 -1
  265. package/dist/ir/function-references.test.js +2 -1
  266. package/dist/ir/function-references.test.js.map +1 -1
  267. package/dist/ir/init-only-globals.d.ts +16 -0
  268. package/dist/ir/init-only-globals.js +121 -0
  269. package/dist/ir/init-only-globals.js.map +1 -0
  270. package/dist/ir/init-only-globals.test.d.ts +1 -0
  271. package/dist/ir/init-only-globals.test.js +115 -0
  272. package/dist/ir/init-only-globals.test.js.map +1 -0
  273. package/dist/ir/initializer-bindings.d.ts +18 -1
  274. package/dist/ir/initializer-bindings.js +91 -1
  275. package/dist/ir/initializer-bindings.js.map +1 -1
  276. package/dist/ir/initializer-bindings.test.js +57 -2
  277. package/dist/ir/initializer-bindings.test.js.map +1 -1
  278. package/dist/ir/int32-slots.d.ts +22 -0
  279. package/dist/ir/int32-slots.js +398 -13
  280. package/dist/ir/int32-slots.js.map +1 -1
  281. package/dist/ir/int32-slots.test.js +119 -8
  282. package/dist/ir/int32-slots.test.js.map +1 -1
  283. package/dist/ir/integer-loop-facts.d.ts +27 -1
  284. package/dist/ir/integer-loop-facts.js +239 -7
  285. package/dist/ir/integer-loop-facts.js.map +1 -1
  286. package/dist/ir/integer-ranges.d.ts +8 -5
  287. package/dist/ir/integer-ranges.js +147 -59
  288. package/dist/ir/integer-ranges.js.map +1 -1
  289. package/dist/ir/integer-ranges.test.js +285 -7
  290. package/dist/ir/integer-ranges.test.js.map +1 -1
  291. package/dist/ir/ir.d.ts +22 -1
  292. package/dist/ir/ir.js +4 -0
  293. package/dist/ir/ir.js.map +1 -1
  294. package/dist/ir/property-bags.d.ts +14 -0
  295. package/dist/ir/property-bags.js +121 -0
  296. package/dist/ir/property-bags.js.map +1 -0
  297. package/dist/ir/receiver-readers.d.ts +21 -0
  298. package/dist/ir/receiver-readers.js +217 -0
  299. package/dist/ir/receiver-readers.js.map +1 -0
  300. package/dist/ir/runtime-features.d.ts +3 -1
  301. package/dist/ir/runtime-features.js +102 -7
  302. package/dist/ir/runtime-features.js.map +1 -1
  303. package/dist/ir/runtime-features.test.js +62 -0
  304. package/dist/ir/runtime-features.test.js.map +1 -1
  305. package/dist/ir/traverse.js +4 -0
  306. package/dist/ir/traverse.js.map +1 -1
  307. package/dist/ir/validate.js +71 -3
  308. package/dist/ir/validate.js.map +1 -1
  309. package/dist/ir/validate.test.js +59 -0
  310. package/dist/ir/validate.test.js.map +1 -1
  311. package/dist/library/int-infer.js +3 -0
  312. package/dist/library/int-infer.js.map +1 -1
  313. package/dist/library/ir-policy.js +5 -0
  314. package/dist/library/ir-policy.js.map +1 -1
  315. package/package.json +20 -20
  316. package/surface-manifest.json +57 -19
@@ -1,3 +1,4 @@
1
+ import { guardNullProto, nullProtoRecordShape, recordNullProtoTest } from "./null-prototype.js";
1
2
  import { lowerProtocolPropertyRead } from "./class-protocol-dispatch.js";
2
3
  import { generatorDrain } from "./iterator-adapters.js";
3
4
  import { lowerEventObjectProperty, lowerEventObjectPropertyWrite } from "./lower-event-target.js";
@@ -5,6 +6,7 @@ import { lowerEventStaticProperty } from "./builtins/numbers.js";
5
6
  import { lowerUnionEquality, tagEqualityMayMissAlias } from "./strict-equality.js";
6
7
  import { isOptionalProcessStreamProperty } from "./builtins/process.js";
7
8
  import { lowerWorkerMetadata } from "./builtins/workers.js";
9
+ import { lowerReadlineProperty } from "./builtins/readline.js";
8
10
  import { lowerBlobInstanceof } from "./builtins/blob.js";
9
11
  import { lowerKeyObjectInstanceof } from "./builtins/key-object.js";
10
12
  import { STATS_TYPE_TESTS } from "./builtins/filesystem.js";
@@ -22,6 +24,7 @@ import { literalUnionArm } from "../union-discriminants.js";
22
24
  * comparisons, nullish coalescing and optional chains, conditions and
23
25
  * ToBoolean/ToString coercion helpers, and field/element reads and writes
24
26
  * (FieldTarget). */
27
+ import { isFsStreamMember, lowerFsStreamProperty } from "./builtins/fs-streams.js";
25
28
  import * as ts from "../ts7/adapter.js";
26
29
  import { isZlibStreamMember, lowerZlibStreamBytesWritten } from "./builtins/compression.js";
27
30
  import { constituentTypes } from "../ts7/checker.js";
@@ -599,7 +602,9 @@ function lowerExprInner(lowerer, expr) {
599
602
  const sym = lowerer.resolveValueSymbol(expr);
600
603
  const projection = sym ? lowerer.staticCallables.get(sym) : undefined;
601
604
  if (projection?.kind === "promisified-exec-file" ||
602
- projection?.kind === "promisified-builtin") {
605
+ projection?.kind === "promisified-exec" ||
606
+ projection?.kind === "promisified-builtin" ||
607
+ projection?.kind === "promisified-zlib") {
603
608
  lowerer.unsupported("SC1090", expr, `a promisified builtin as a value (call '${expr.text}' directly)`);
604
609
  }
605
610
  if (projection?.kind === "builtin-function") {
@@ -1554,6 +1559,18 @@ function lowerExprInner(lowerer, expr) {
1554
1559
  });
1555
1560
  return { kind: "closure", fnName: name, captures: [], type: funcOf([DYN], DYN), loc };
1556
1561
  }
1562
+ // An Hmac has no copy() (Hash does): Node answers undefined, which
1563
+ // `typeof mac.copy` feature checks read. TypeScript rejects the read.
1564
+ if (expr.name.text === "copy" &&
1565
+ lowerer.mapTypeOf(lowerer.typeOf(expr.expression))?.kind === "cryptoHmac") {
1566
+ return {
1567
+ kind: "seqExpr",
1568
+ stmts: [{ kind: "exprStmt", expr: lowerer.lowerExpr(expr.expression), loc }],
1569
+ result: dynUndefinedExpr(loc),
1570
+ type: DYN,
1571
+ loc,
1572
+ };
1573
+ }
1557
1574
  if (lowerer.stdlibGlobalMember(expr, "globalThis") === "console") {
1558
1575
  return { kind: "libCall", fn: "console.native", args: [], type: DYN, loc };
1559
1576
  }
@@ -1828,6 +1845,9 @@ function lowerExprInner(lowerer, expr) {
1828
1845
  // diagnostics_channel Channel receivers — name/hasSubscribers
1829
1846
  // over the f64 channel handle.
1830
1847
  lowerer.lowerDiagnosticsChannelProperty(expr) ??
1848
+ // readline Interface receivers — the history and option members
1849
+ // over the f64 interface handle.
1850
+ lowerReadlineProperty(lowerer, expr) ??
1831
1851
  // TracingChannel receivers — the five event channels and
1832
1852
  // hasSubscribers over the f64 tracing handle.
1833
1853
  lowerer.lowerTracingChannelProperty(expr) ??
@@ -4166,6 +4186,8 @@ export function lowerIntrinsicProperty(lowerer, expr) {
4166
4186
  const numberMember = lowerer.stdlibGlobalMember(expr, "Number");
4167
4187
  if (numberMember === "parseInt" || numberMember === "parseFloat")
4168
4188
  return lowerNumberParserValue(lowerer, numberMember, locOf(expr));
4189
+ if (lowerer.stdlibGlobalMember(expr, "Buffer") === "poolSize")
4190
+ return { kind: "libCall", fn: "buffer.poolSize", args: [], type: F64, loc: locOf(expr) };
4169
4191
  if (lowerer.stdlibGlobalMember(expr, "Buffer") === "isBuffer")
4170
4192
  return lowerCheckedPredicateValue(lowerer, "Buffer.isBuffer", "buffer", locOf(expr));
4171
4193
  if (lowerer.stdlibGlobalMember(expr, "Date") === "now")
@@ -6343,6 +6365,21 @@ function tupleLiteralIndex(node) {
6343
6365
  * change the target or the value used by the operator. The expression yields
6344
6366
  * the computed value before a typed array or Buffer coerces it for storage. */
6345
6367
  export function lowerElementCompound(lowerer, expr, op) {
6368
+ const lowered = lowerElementCompoundParts(lowerer, expr, op, false);
6369
+ if (!lowered.expr)
6370
+ throw new InternalCompilerError("a compound element value lowered to statements");
6371
+ return lowered.expr;
6372
+ }
6373
+ /** `a[i] op= rhs` in statement position: a string array append becomes the
6374
+ * canonical `a[i] = a[i] + rhs` store (receiver and index saved first),
6375
+ * which the backend appends in place; other forms keep the value path. */
6376
+ export function lowerElementCompoundStatement(lowerer, expr, op) {
6377
+ const lowered = lowerElementCompoundParts(lowerer, expr, op, true);
6378
+ if (lowered.stmts)
6379
+ return { kind: "block", body: lowered.stmts, loc: locOf(expr) };
6380
+ return { kind: "exprStmt", expr: lowered.expr, loc: locOf(expr) };
6381
+ }
6382
+ function lowerElementCompoundParts(lowerer, expr, op, statement) {
6346
6383
  const target = expr.left;
6347
6384
  fenceNodeModuleMutation(lowerer, target, "assignment");
6348
6385
  const loc = locOf(expr);
@@ -6377,7 +6414,7 @@ export function lowerElementCompound(lowerer, expr, op) {
6377
6414
  },
6378
6415
  loc,
6379
6416
  });
6380
- return { kind: "seqExpr", stmts, result: value, type: DYN, loc };
6417
+ return { expr: { kind: "seqExpr", stmts, result: value, type: DYN, loc }, stmts: null };
6381
6418
  }
6382
6419
  const receiverType = checked.type.kind === "array" || checked.type.kind === "bytes"
6383
6420
  ? checked.type
@@ -6435,6 +6472,27 @@ export function lowerElementCompound(lowerer, expr, op) {
6435
6472
  const valueType = elementType.kind === "union" && lowerer.armTag(elementType.unionId, UNDEFINED_T) >= 0
6436
6473
  ? lowerer.stripUndefinedArm(elementType)
6437
6474
  : elementType;
6475
+ if (statement &&
6476
+ op === "+" &&
6477
+ receiver.type.kind === "array" &&
6478
+ receiver.type.elem.kind === "string") {
6479
+ // Receiver, index, old element (read inside the concat), rhs, write.
6480
+ const appended = {
6481
+ kind: "strConcat",
6482
+ left: oldValue,
6483
+ right: lowerer.ensureString(rhs, expr.right),
6484
+ type: STRING,
6485
+ loc,
6486
+ };
6487
+ return {
6488
+ expr: null,
6489
+ stmts: [
6490
+ { kind: "varDecl", localId: receiverLocal.id, init: receiver, loc },
6491
+ { kind: "varDecl", localId: indexLocal.id, init: index, loc },
6492
+ { kind: "arraySet", arr: receiverRef(), index: indexRef(), value: appended, loc },
6493
+ ],
6494
+ };
6495
+ }
6438
6496
  let computed;
6439
6497
  if (op === "+" && valueType.kind === "string") {
6440
6498
  computed = {
@@ -6457,17 +6515,18 @@ export function lowerElementCompound(lowerer, expr, op) {
6457
6515
  }
6458
6516
  else if (valueType.kind === "dyn" && isJsSourceFile(expr.getSourceFile())) {
6459
6517
  const left = lowerer.coerceToExpected(oldRef(), DYN), right = lowerer.coerceToExpected(rhs, DYN);
6460
- const numeric = ["-", "*", "/", "%", "**"].includes(op);
6461
- computed = {
6462
- kind: "libCall",
6463
- fn: op === "+" ? "dyn.add" : numeric ? "dyn.arithmetic" : "dyn.bitwise",
6464
- args: op === "+" ? [left, right] : [left, right, strLit(op, loc)],
6465
- type: DYN,
6466
- loc,
6467
- };
6518
+ computed = dynCompoundValue(op, left, right, loc);
6519
+ }
6520
+ else if (rhs.type.kind === "dyn" &&
6521
+ receiver.type.kind === "array" &&
6522
+ lowerer.dynConvertible(oldValue.type) &&
6523
+ lowerer.dynConvertible(valueType)) {
6524
+ // An untyped right operand: the expanded `a[i] = a[i] op rhs`, checked
6525
+ // back into the element type.
6526
+ computed = lowerer.coerceInto(expr, dynCompoundValue(op, lowerer.coerceToExpected(oldRef(), DYN), lowerer.coerceToExpected(rhs, DYN), loc), valueType);
6468
6527
  }
6469
6528
  else {
6470
- lowerer.unsupported("SC1043", expr);
6529
+ compoundUnsupported(lowerer, expr, op, oldValue.type, rhs.type);
6471
6530
  }
6472
6531
  const resultLocal = lowerer.declareHiddenLocal("%compoundResult", computed.type);
6473
6532
  const resultRef = () => varRef(resultLocal.id, computed.type, loc);
@@ -6475,17 +6534,20 @@ export function lowerElementCompound(lowerer, expr, op) {
6475
6534
  ? arrayValueStore(lowerer, receiverRef(), indexRef(), resultRef(), receiver.type.elem, loc)
6476
6535
  : { kind: "bytesSet", arr: receiverRef(), index: indexRef(), value: resultRef(), loc };
6477
6536
  return {
6478
- kind: "seqExpr",
6479
- stmts: [
6480
- { kind: "varDecl", localId: receiverLocal.id, init: receiver, loc },
6481
- { kind: "varDecl", localId: indexLocal.id, init: index, loc },
6482
- { kind: "varDecl", localId: oldLocal.id, init: oldValue, loc },
6483
- { kind: "varDecl", localId: resultLocal.id, init: computed, loc },
6484
- write,
6485
- ],
6486
- result: resultRef(),
6487
- type: computed.type,
6488
- loc,
6537
+ expr: {
6538
+ kind: "seqExpr",
6539
+ stmts: [
6540
+ { kind: "varDecl", localId: receiverLocal.id, init: receiver, loc },
6541
+ { kind: "varDecl", localId: indexLocal.id, init: index, loc },
6542
+ { kind: "varDecl", localId: oldLocal.id, init: oldValue, loc },
6543
+ { kind: "varDecl", localId: resultLocal.id, init: computed, loc },
6544
+ write,
6545
+ ],
6546
+ result: resultRef(),
6547
+ type: computed.type,
6548
+ loc,
6549
+ },
6550
+ stmts: null,
6489
6551
  };
6490
6552
  }
6491
6553
  /** ToString of one stabilized `string[]` element read for `+=`: a missing
@@ -7176,6 +7238,11 @@ export function ensureString(lowerer, e, node) {
7176
7238
  if (isPerfEntryType(lowerer, e.type))
7177
7239
  return perfEntryTag(lowerer, e, e.type, e.loc);
7178
7240
  if (shape && !shape.tuple && !shape.fields.some((f) => f.name === "toString")) {
7241
+ // A null-prototype record (Object.groupBy) has no toString or
7242
+ // valueOf: ToPrimitive throws Node's TypeError.
7243
+ const nullProtoT = nullProtoRecordShape(lowerer, e.type);
7244
+ if (nullProtoT)
7245
+ return nullProtoToString(lowerer, e, nullProtoT);
7179
7246
  return { kind: "toString", operand: e, type: STRING, loc: e.loc };
7180
7247
  }
7181
7248
  }
@@ -7183,6 +7250,34 @@ export function ensureString(lowerer, e, node) {
7183
7250
  lowerer.badType(node, lowerer.typeOf(node));
7184
7251
  return { kind: "toString", operand: e, type: STRING, loc: e.loc };
7185
7252
  }
7253
+ /** String(r) over a record that may have a null prototype: an interned
7254
+ * helper that throws Node's TypeError for a null-prototype record and
7255
+ * answers "[object Object]" otherwise. */
7256
+ function nullProtoToString(lowerer, e, t) {
7257
+ const loc = e.loc;
7258
+ const key = `nullProtoToString:${t.shapeId}`;
7259
+ let helper = lowerer.valueHelpers.get(key);
7260
+ if (!helper) {
7261
+ helper = `%rec.tostr.${lowerer.valueHelpers.size}`;
7262
+ lowerer.valueHelpers.set(key, helper);
7263
+ const r = varRef("r.0", t, loc);
7264
+ lowerer.liftedFns.push({
7265
+ name: helper,
7266
+ params: [{ localId: "r.0", name: "r", type: t }],
7267
+ returnType: STRING,
7268
+ locals: [{ id: "r.0", name: "r", type: t, mutable: false }],
7269
+ body: [
7270
+ {
7271
+ kind: "return",
7272
+ value: guardNullProto(r, t.shapeId, "Cannot convert object to primitive value", { kind: "toString", operand: r, type: STRING, loc }, loc),
7273
+ loc,
7274
+ },
7275
+ ],
7276
+ loc,
7277
+ });
7278
+ }
7279
+ return { kind: "call", callee: helper, args: [e], type: STRING, loc };
7280
+ }
7186
7281
  /** `new String(x)` (stdlib provenance, ≤1 argument) in a ToString
7187
7282
  * position: the wrapper's only distinguishers are typeof and identity —
7188
7283
  * neither is observable where the value immediately stringifies — so the
@@ -7319,6 +7414,11 @@ export function lowerAsExpression(lowerer, expr) {
7319
7414
  // object. Box a live reference instead of erasing the assertion and
7320
7415
  // handing native storage to a checked-dynamic property operation.
7321
7416
  if (target?.kind === "dyn" && (targetTs0.flags & ts.TypeFlags.Object) !== 0) {
7417
+ // A class instance asserted to a class-backed protocol view (a type
7418
+ // class instances flow into): the same identity-keeping box an
7419
+ // implicit flow into the view uses.
7420
+ if (inner.type.kind === "object" && lowerer.classImplementedProtocol(targetTs0))
7421
+ return lowerer.coerceInto(expr, inner, DYN);
7322
7422
  const sourceShape = inner.type.kind === "record" ? lowerer.shapes.get(inner.type.shapeId) : undefined;
7323
7423
  if (hasClassPayload(lowerer, inner.type) ||
7324
7424
  (sourceShape && shapeHasAccessorSlots(sourceShape))) {
@@ -7477,7 +7577,7 @@ export function lowerPrefixUnary(lowerer, expr) {
7477
7577
  ? { kind: "dynCheck", value: raw, type: F64, loc }
7478
7578
  : lowerOptionalNumber(lowerer, raw, loc, expr.operand);
7479
7579
  if (operand.type.kind !== "f64")
7480
- lowerer.unsupported("SC1043", expr);
7580
+ operatorUnsupported(lowerer, expr, "-", [raw.type]);
7481
7581
  if (operand.kind === "numLit")
7482
7582
  return { ...operand, value: -operand.value, loc };
7483
7583
  return { kind: "unary", op: "-", operand, type: F64, loc };
@@ -7495,7 +7595,7 @@ export function lowerPrefixUnary(lowerer, expr) {
7495
7595
  }
7496
7596
  const operand = lowerOptionalNumber(lowerer, raw, loc, expr.operand);
7497
7597
  if (operand.type.kind !== "f64")
7498
- lowerer.unsupported("SC1043", expr);
7598
+ operatorUnsupported(lowerer, expr, "+", [raw.type]);
7499
7599
  return operand;
7500
7600
  }
7501
7601
  case ts.SyntaxKind.ExclamationToken: {
@@ -7524,7 +7624,7 @@ export function lowerPrefixUnary(lowerer, expr) {
7524
7624
  // otherwise numeric slot to the checked-dynamic tree.
7525
7625
  const operand = lowerOptionalNumber(lowerer, raw, loc, expr.operand);
7526
7626
  if (operand.type.kind !== "f64")
7527
- lowerer.unsupported("SC1043", expr);
7627
+ operatorUnsupported(lowerer, expr, "~", [raw.type]);
7528
7628
  return { kind: "unary", op: "~", operand, type: F64, loc };
7529
7629
  }
7530
7630
  case ts.SyntaxKind.PlusPlusToken:
@@ -7633,12 +7733,19 @@ export function lowerIncDec(lowerer, expr, prefix) {
7633
7733
  loc,
7634
7734
  });
7635
7735
  }
7636
- if (isJsSourceFile(expr.getSourceFile()) && raw.type.kind === "dyn") {
7736
+ // A TS member statically typed number on a checked-dynamic receiver (a
7737
+ // class-backed protocol view): the expanded form `o.v = o.v + 1`, its
7738
+ // read checked into number like any other read of the member.
7739
+ const checkedNumber = !isJsSourceFile(expr.getSourceFile()) &&
7740
+ raw.type.kind === "dyn" &&
7741
+ lowerer.mapTypeOf(lowerer.typeOf(access))?.kind === "f64";
7742
+ if ((isJsSourceFile(expr.getSourceFile()) || checkedNumber) && raw.type.kind === "dyn") {
7637
7743
  const receiver = save(raw, "%incrementReceiver");
7638
7744
  const key = save(ts.isElementAccessExpression(access)
7639
7745
  ? lowerer.lowerExprExpecting(access.argumentExpression, DYN)
7640
7746
  : lowerer.coerceInto(access, { kind: "strLit", value: access.name.text, type: STRING, loc }, DYN), "%incrementKey");
7641
- return finish({ kind: "dynKeyGet", value: receiver, key, type: DYN, loc }, (value) => ({
7747
+ const read = { kind: "dynKeyGet", value: receiver, key, type: DYN, loc };
7748
+ return finish(checkedNumber ? lowerer.coerceInto(access, read, F64) : read, (value) => ({
7642
7749
  kind: "exprStmt",
7643
7750
  expr: {
7644
7751
  kind: "libCall",
@@ -7781,7 +7888,7 @@ export function lowerIncDecTarget(lowerer, expr, target, prefix) {
7781
7888
  };
7782
7889
  }
7783
7890
  if (target.type.kind !== "f64")
7784
- lowerer.unsupported("SC1043", expr);
7891
+ operatorUnsupported(lowerer, expr, op === "+" ? "++" : "--", [target.type]);
7785
7892
  return { kind: "incDec", op, prefix, localId: target.id, type: F64, loc };
7786
7893
  }
7787
7894
  /** Whether a lowered statement can live inside a seqExpr. These statements
@@ -7874,26 +7981,51 @@ export function lowerCompoundValueToTarget(lowerer, expr, compound, target) {
7874
7981
  if (numericRead.type.kind === "f64" && numericRhs.type.kind === "f64") {
7875
7982
  return lowerer.coerceInto(expr, { kind: "bin", op: compound, left: numericRead, right: numericRhs, type: F64, loc }, target.type);
7876
7983
  }
7984
+ // An untyped operand: exactly the expanded `x = x op rhs` — the runtime
7985
+ // operator on both values, then the checked conversion into the
7986
+ // target's declared type (a string result for a number target throws the
7987
+ // catchable TypeError, as the expanded assignment does).
7877
7988
  if ((target.type.kind === "dyn" || rhs.type.kind === "dyn") &&
7878
- isJsSourceFile(expr.getSourceFile())) {
7989
+ (isJsSourceFile(expr.getSourceFile()) ||
7990
+ (lowerer.dynConvertible(read.type) && lowerer.dynConvertible(rhs.type)))) {
7879
7991
  const left = lowerer.coerceInto(expr.left, read, DYN);
7880
7992
  const right = lowerer.coerceInto(expr.right, rhs, DYN);
7881
- const numeric = ["-", "*", "/", "%", "**"].includes(compound);
7882
- const computed = {
7883
- kind: "libCall",
7884
- fn: compound === "+" ? "dyn.add" : numeric ? "dyn.arithmetic" : "dyn.bitwise",
7885
- args: compound === "+"
7886
- ? [left, right]
7887
- : [left, right, { kind: "strLit", value: compound, type: STRING, loc }],
7888
- type: DYN,
7889
- loc,
7890
- };
7891
- return lowerer.coerceInto(expr, computed, target.type);
7993
+ return lowerer.coerceInto(expr, dynCompoundValue(compound, left, right, loc), target.type);
7892
7994
  }
7893
7995
  const bigint = bigintCompoundValue(compound, read, rhs, loc);
7894
7996
  if (bigint)
7895
7997
  return bigint;
7896
- lowerer.unsupported("SC1043", expr);
7998
+ compoundUnsupported(lowerer, expr, compound, read.type, rhs.type);
7999
+ }
8000
+ /** The runtime operator of a compound assignment over two checked-dynamic
8001
+ * operands (Node's ToPrimitive/ToNumeric order lives in the runtime). */
8002
+ function dynCompoundValue(op, left, right, loc) {
8003
+ const numeric = ["-", "*", "/", "%", "**"].includes(op);
8004
+ return {
8005
+ kind: "libCall",
8006
+ fn: op === "+" ? "dyn.add" : numeric ? "dyn.arithmetic" : "dyn.bitwise",
8007
+ args: op === "+" ? [left, right] : [left, right, strLit(op, loc)],
8008
+ type: DYN,
8009
+ loc,
8010
+ };
8011
+ }
8012
+ /** An operand type in an SC1043 message: checked-dynamic values (`any`,
8013
+ * `unknown`) are "untyped", everything else its quoted type. */
8014
+ function operandText(lowerer, t) {
8015
+ return t.kind === "dyn" ? "untyped" : `'${lowerer.fmt(t)}'`;
8016
+ }
8017
+ /** SC1043 for a compound assignment whose operand types have no lowering,
8018
+ * naming the operator and both types rather than the comparison wording. */
8019
+ function compoundUnsupported(lowerer, node, op, target, value) {
8020
+ lowerer.unsupported("SC1043", node, `compound '${op}=' assignments of ${operandText(lowerer, value)} values to ${operandText(lowerer, target)} targets`);
8021
+ }
8022
+ /** SC1043 for an arithmetic, unary or update operator whose operand types
8023
+ * have no lowering (comparisons keep the registry wording). */
8024
+ function operatorUnsupported(lowerer, node, op, operands) {
8025
+ const [first, second] = operands;
8026
+ lowerer.unsupported("SC1043", node, second === undefined
8027
+ ? `'${op}' operations on ${operandText(lowerer, first)} values`
8028
+ : `'${op}' operations on ${operandText(lowerer, first)} and ${operandText(lowerer, second)} values`);
7897
8029
  }
7898
8030
  /** Equality of two NaN-coded values (nan-coded-reads.ts), each of which may
7899
8031
  * stand for undefined and never holds a genuine NaN: Node's undefined equals
@@ -8782,7 +8914,7 @@ export function lowerBinary(lowerer, expr) {
8782
8914
  };
8783
8915
  }
8784
8916
  }
8785
- lowerer.unsupported("SC1043", expr);
8917
+ operatorUnsupported(lowerer, expr, "+", [left.type, right.type]);
8786
8918
  break;
8787
8919
  case ts.SyntaxKind.MinusToken:
8788
8920
  case ts.SyntaxKind.AsteriskToken:
@@ -8790,7 +8922,7 @@ export function lowerBinary(lowerer, expr) {
8790
8922
  case ts.SyntaxKind.PercentToken:
8791
8923
  case ts.SyntaxKind.AsteriskAsteriskToken: {
8792
8924
  if (!bothNum)
8793
- lowerer.unsupported("SC1043", expr);
8925
+ operatorUnsupported(lowerer, expr, ts.tokenToString(op) ?? "?", [left.type, right.type]);
8794
8926
  const binOp = op === ts.SyntaxKind.MinusToken
8795
8927
  ? "-"
8796
8928
  : op === ts.SyntaxKind.AsteriskToken
@@ -8820,7 +8952,7 @@ export function lowerBinary(lowerer, expr) {
8820
8952
  case ts.SyntaxKind.GreaterThanGreaterThanToken:
8821
8953
  case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: {
8822
8954
  if (!bothNum)
8823
- lowerer.unsupported("SC1043", expr);
8955
+ operatorUnsupported(lowerer, expr, ts.tokenToString(op) ?? "?", [left.type, right.type]);
8824
8956
  const bitOp = op === ts.SyntaxKind.AmpersandToken
8825
8957
  ? "&"
8826
8958
  : op === ts.SyntaxKind.BarToken
@@ -10533,10 +10665,12 @@ export function lowerInstanceOf(lowerer, expr, loc) {
10533
10665
  if (left.type.kind === "union") {
10534
10666
  const unionId = left.type.unionId;
10535
10667
  const arms = lowerer.unions.get(unionId)?.arms;
10536
- // Ordinary records and scalar values do not carry a class prototype.
10537
- // Dynamic/opaque runtime objects keep their existing instanceof fences.
10668
+ // Ordinary records, arrays and scalar values do not carry a class
10669
+ // prototype (no program class extends Array). Dynamic/opaque runtime
10670
+ // objects keep their existing instanceof fences.
10538
10671
  if (arms?.every((arm) => arm.kind === "object" ||
10539
10672
  arm.kind === "record" ||
10673
+ arm.kind === "array" ||
10540
10674
  arm.kind === "f64" ||
10541
10675
  arm.kind === "string" ||
10542
10676
  arm.kind === "bool" ||
@@ -10595,6 +10729,10 @@ export function lowerInstanceOf(lowerer, expr, loc) {
10595
10729
  }
10596
10730
  return { kind: "call", callee: helper, args: [left], type: BOOL, loc };
10597
10731
  }
10732
+ // A class arm could hold an instance: the test cannot be decided
10733
+ // statically.
10734
+ if (arms?.some((arm) => arm.kind === "object"))
10735
+ lowerer.unsupported("SC1090", expr, "'instanceof' on a union of class instances and values without a class prototype test");
10598
10736
  }
10599
10737
  if (left.type.kind !== "object") {
10600
10738
  return readsClassAfter(lowerer, target, expr.right, [{ kind: "exprStmt", expr: left, loc }], {
@@ -11182,6 +11320,17 @@ function lowerInExpression(lowerer, expr, loc) {
11182
11320
  recv.kind === "recordGet" ||
11183
11321
  recv.kind === "fieldGet" ||
11184
11322
  pureRecvNode) {
11323
+ // A null-prototype record (Object.groupBy) has no inherited names.
11324
+ const nullProtoT = inherited ? nullProtoRecordShape(lowerer, recv.type) : null;
11325
+ if (nullProtoT) {
11326
+ return {
11327
+ kind: "unary",
11328
+ op: "!",
11329
+ operand: recordNullProtoTest(recv, nullProtoT.shapeId, loc),
11330
+ type: BOOL,
11331
+ loc,
11332
+ };
11333
+ }
11185
11334
  return { kind: "boolLit", value: inherited, type: BOOL, loc };
11186
11335
  }
11187
11336
  lowerer.unsupported("SC1090", expr, "statically-decided 'in' on computed receivers (bind the value to a variable first)");
@@ -11243,20 +11392,34 @@ function lowerRuntimeKeyIn(lowerer, expr, loc) {
11243
11392
  type: BOOL,
11244
11393
  loc,
11245
11394
  };
11246
- // A miss in the record's own keys still finds Object.prototype's.
11247
- let inherited = ovfHas;
11395
+ // A miss in the record's own keys still finds Object.prototype's,
11396
+ // unless the record has a null prototype (Object.groupBy).
11397
+ let protoName = null;
11248
11398
  for (const name of OBJECT_PROTOTYPE_KEYS) {
11249
11399
  if (shape.fields.some((f) => f.name === name))
11250
11400
  continue;
11251
- inherited = {
11401
+ const eq = {
11402
+ kind: "strEq",
11403
+ negated: false,
11404
+ left: k,
11405
+ right: { kind: "strLit", value: name, type: STRING, loc },
11406
+ type: BOOL,
11407
+ loc,
11408
+ };
11409
+ protoName =
11410
+ protoName === null
11411
+ ? eq
11412
+ : { kind: "logical", op: "||", left: protoName, right: eq, type: BOOL, loc };
11413
+ }
11414
+ if (protoName !== null && nullProtoRecordShape(lowerer, recT)) {
11415
+ protoName = {
11252
11416
  kind: "logical",
11253
- op: "||",
11254
- left: inherited,
11417
+ op: "&&",
11418
+ left: protoName,
11255
11419
  right: {
11256
- kind: "strEq",
11257
- negated: false,
11258
- left: k,
11259
- right: { kind: "strLit", value: name, type: STRING, loc },
11420
+ kind: "unary",
11421
+ op: "!",
11422
+ operand: recordNullProtoTest(r, recvT.shapeId, loc),
11260
11423
  type: BOOL,
11261
11424
  loc,
11262
11425
  },
@@ -11264,7 +11427,9 @@ function lowerRuntimeKeyIn(lowerer, expr, loc) {
11264
11427
  loc,
11265
11428
  };
11266
11429
  }
11267
- body.push(ret(inherited));
11430
+ body.push(ret(protoName === null
11431
+ ? ovfHas
11432
+ : { kind: "logical", op: "||", left: ovfHas, right: protoName, type: BOOL, loc }));
11268
11433
  lowerer.liftedFns.push({
11269
11434
  name: helper,
11270
11435
  params: [
@@ -11587,6 +11752,10 @@ function lowerMatchGroupsRead(lowerer, expr) {
11587
11752
  if (!recvT || !isMatchSliceType(lowerer, recvT) || !lowerer.isStdlibMember(expr))
11588
11753
  return null;
11589
11754
  const groups = matchResultNamedGroupsOf(lowerer, expr.expression);
11755
+ // An untraced regex: TypeScript reaches the member fence; JavaScript
11756
+ // would otherwise read the slice's absent expando as undefined.
11757
+ if (groups === null && isJsSourceFile(expr.getSourceFile()))
11758
+ lowerer.stdlibMemberFence(expr);
11590
11759
  if (groups === null)
11591
11760
  return null;
11592
11761
  if (groups.length === 0) {
@@ -13143,7 +13312,7 @@ function lowerFieldCompoundValue(lowerer, access, op, rhsNode, loc) {
13143
13312
  ? { kind: "dynCheck", value: rhs, type: F64, loc: rhs.loc }
13144
13313
  : lowerOptionalNumber(lowerer, rhs, loc);
13145
13314
  if (numericRhs.type.kind !== "f64")
13146
- lowerer.unsupported("SC1043", access);
13315
+ compoundUnsupported(lowerer, access, op, F64, numericRhs.type);
13147
13316
  const value = save({ kind: "bin", op, left: cur, right: numericRhs, type: F64, loc }, "%compoundResult");
13148
13317
  const boxed = { kind: "dynFrom", value, type: DYN, loc };
13149
13318
  body.push({
@@ -13204,22 +13373,16 @@ function lowerFieldCompoundValue(lowerer, access, op, rhsNode, loc) {
13204
13373
  else if (bigintValue) {
13205
13374
  value = bigintValue;
13206
13375
  }
13207
- else if (target.fieldType.kind === "dyn" && isJsSourceFile(access.getSourceFile())) {
13208
- const numeric = ["-", "*", "/", "%", "**"].includes(op);
13209
- const left = lowerer.coerceToExpected(read, DYN);
13210
- const right = lowerer.coerceToExpected(rhs, DYN);
13211
- value = {
13212
- kind: "libCall",
13213
- fn: op === "+" ? "dyn.add" : numeric ? "dyn.arithmetic" : "dyn.bitwise",
13214
- args: op === "+"
13215
- ? [left, right]
13216
- : [left, right, { kind: "strLit", value: op, type: STRING, loc }],
13217
- type: DYN,
13218
- loc,
13219
- };
13376
+ else if ((target.fieldType.kind === "dyn" && isJsSourceFile(access.getSourceFile())) ||
13377
+ // An untyped right operand: the expanded `o.f = o.f op rhs`; the field
13378
+ // write below checks the result into the declared field type.
13379
+ (rhs.type.kind === "dyn" &&
13380
+ lowerer.dynConvertible(read.type) &&
13381
+ lowerer.dynConvertible(target.fieldType))) {
13382
+ value = dynCompoundValue(op, lowerer.coerceToExpected(read, DYN), lowerer.coerceToExpected(rhs, DYN), loc);
13220
13383
  }
13221
13384
  else {
13222
- lowerer.unsupported("SC1043", access);
13385
+ compoundUnsupported(lowerer, access, op, read.type, rhs.type);
13223
13386
  }
13224
13387
  if (storedString && rhs.type.kind === "string" && read.kind === "varRef" && appended !== null) {
13225
13388
  // The field gives up its value before the concat (no code runs in
@@ -13260,6 +13423,11 @@ function lowerStreamObjectProperty(lowerer, expr) {
13260
13423
  if (expr.name.text === "bytesWritten" && isZlibStreamMember(lowerer, expr)) {
13261
13424
  return lowerZlibStreamBytesWritten(lowerer, expr);
13262
13425
  }
13426
+ if (isFsStreamMember(lowerer, expr)) {
13427
+ const member = lowerFsStreamProperty(lowerer, expr);
13428
+ if (member)
13429
+ return member;
13430
+ }
13263
13431
  return lowerStreamProperty(lowerer, expr, info);
13264
13432
  }
13265
13433
  /** The primitive-constructor closure (`String`/`Number`/`Boolean` as a