@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,5 +1,6 @@
1
1
  /* node:test's mock functions (Node 24.22, lib/internal/test_runner/mock):
2
- * mock.fn and t.mock.fn, and the fn.mock context's calls, callCount,
2
+ * mock.fn, mock.method and their t.mock twins, the trackers' restoreAll
3
+ * and reset, and the fn.mock context's calls, callCount,
3
4
  * mockImplementation, mockImplementationOnce, resetCalls and restore.
4
5
  *
5
6
  * mock.fn(original, implementation?) lowers to the hybrid record
@@ -8,11 +9,21 @@
8
9
  * one-time implementation registered for this call index, or the current
9
10
  * one, calls it, and appends { arguments, error, result, this } to the
10
11
  * calls log before returning or rethrowing. The context's mutating
11
- * methods are lifted helpers of the same type. */
12
+ * methods are lifted helpers of the same type.
13
+ *
14
+ * mock.method(object, name, implementation?) mocks a function-valued field
15
+ * of a record: the field gets a second wrapper over the same context, one
16
+ * that records the object as `this`, and the context's %unmock closure
17
+ * writes the original back on restore(). Each mock registers a closure
18
+ * that calls its restore() with its tracker (scr_test.c): the module's
19
+ * `mock`, or the test's t.mock, which is reset when the test ends. */
12
20
  import * as ts from "../ts7/adapter.js";
13
21
  import { BOOL, CAUGHT, DYN, F64, UNDEFINED_T, VOID, typeKey, } from "../../ir/ir.js";
14
22
  import { countedFor, dynUndefinedExpr, numLit, varRef } from "../../ir/build.js";
23
+ import { mockType as mockHybridType } from "../mock-shapes.js";
15
24
  import { locOf } from "../program.js";
25
+ import { resultIsDiscarded } from "./call-position.js";
26
+ const RESTORE_FN = { kind: "func", params: [], ret: VOID };
16
27
  /** The context record's parts, or null when `type` is not a mock context
17
28
  * (mock-shapes.ts). */
18
29
  function mockContextFields(lowerer, type) {
@@ -23,9 +34,11 @@ function mockContextFields(lowerer, type) {
23
34
  const impl = field("%impl");
24
35
  const once = field("%once");
25
36
  const calls = field("calls");
37
+ const unmock = field("%unmock");
26
38
  if (impl?.kind !== "func" ||
27
39
  once?.kind !== "array" ||
28
40
  calls?.kind !== "array" ||
41
+ unmock?.kind !== "array" ||
29
42
  field("%original") === undefined)
30
43
  return null;
31
44
  const call = calls.elem;
@@ -34,7 +47,7 @@ function mockContextFields(lowerer, type) {
34
47
  const args = callShape?.fields.find((f) => f.name === "arguments")?.type;
35
48
  if (!result || !args)
36
49
  return null;
37
- return { fn: impl, call, calls, once, onceEntry: once.elem, result, args };
50
+ return { fn: impl, call, calls, once, onceEntry: once.elem, unmock, result, args };
38
51
  }
39
52
  export function isMockContextType(lowerer, type) {
40
53
  return mockContextFields(lowerer, type) !== null;
@@ -69,9 +82,15 @@ const local = (id, name, type, mutable = false) => ({
69
82
  type,
70
83
  mutable,
71
84
  });
72
- /** Lifts one function per (context type, role), cached on the lowerer. */
73
- function liftOnce(lowerer, ctxType, role, build) {
74
- const key = `mock.${role}:${ctxType.shapeId}`;
85
+ /** A captured local of a lifted closure. */
86
+ const boxedLocal = (id, name, type) => ({
87
+ ...local(id, name, type),
88
+ boxed: true,
89
+ });
90
+ /** Lifts one function per (context type, role), cached on the lowerer.
91
+ * `owner` overrides the context type's shape as the cache key. */
92
+ function liftOnce(lowerer, ctxType, role, build, owner = ctxType.shapeId) {
93
+ const key = `mock.${role}:${owner}`;
75
94
  const existing = lowerer.assertHelpers.get(key);
76
95
  if (existing)
77
96
  return existing;
@@ -80,9 +99,10 @@ function liftOnce(lowerer, ctxType, role, build) {
80
99
  build(name);
81
100
  return name;
82
101
  }
83
- /** `%mock.wrap.N(ctx)`: the closure that records each call into ctx. */
84
- function mockWrapperFactory(lowerer, ctxType, loc) {
85
- return liftOnce(lowerer, ctxType, "wrap", (name) => {
102
+ /** `%mock.wrap.N(ctx)`: the closure that records each call into ctx, with
103
+ * `this` undefined. `%mock.wrapMethod.N(ctx, this)` records `this`. */
104
+ function mockWrapperFactory(lowerer, ctxType, loc, withThis = false) {
105
+ return liftOnce(lowerer, ctxType, withThis ? "wrapMethod" : "wrap", (name) => {
86
106
  const { fn, call, calls, once, onceEntry, result, args } = mockContextFields(lowerer, ctxType);
87
107
  const impl = `${name}.impl`;
88
108
  const ctx = () => varRef("ctx.0", ctxType, loc);
@@ -90,12 +110,14 @@ function mockWrapperFactory(lowerer, ctxType, loc) {
90
110
  const paramRefs = () => params.map((p) => varRef(p.localId, p.type, loc));
91
111
  const argumentsValue = () => fn.rest
92
112
  ? paramRefs()[0]
93
- : {
94
- kind: "recordLit",
95
- fields: paramRefs().map((value, i) => ({ name: String(i), value })),
96
- type: args,
97
- loc,
98
- };
113
+ : args.kind === "array"
114
+ ? { kind: "arrayLit", elems: [], type: args, loc }
115
+ : {
116
+ kind: "recordLit",
117
+ fields: paramRefs().map((value, i) => ({ name: String(i), value })),
118
+ type: args,
119
+ loc,
120
+ };
99
121
  const record = (resultValue, error) => ({
100
122
  kind: "exprStmt",
101
123
  expr: {
@@ -109,7 +131,10 @@ function mockWrapperFactory(lowerer, ctxType, loc) {
109
131
  { name: "arguments", value: argumentsValue() },
110
132
  { name: "error", value: error },
111
133
  { name: "result", value: resultValue },
112
- { name: "this", value: dynUndefinedExpr(loc) },
134
+ {
135
+ name: "this",
136
+ value: withThis ? varRef("this.0", DYN, loc) : dynUndefinedExpr(loc),
137
+ },
113
138
  ],
114
139
  type: call,
115
140
  loc,
@@ -217,10 +242,14 @@ function mockWrapperFactory(lowerer, ctxType, loc) {
217
242
  name: impl,
218
243
  params,
219
244
  returnType: fn.ret,
220
- captures: [{ localId: "ctx.0", name: "ctx", type: ctxType }],
245
+ captures: [
246
+ { localId: "ctx.0", name: "ctx", type: ctxType },
247
+ ...(withThis ? [{ localId: "this.0", name: "this", type: DYN }] : []),
248
+ ],
221
249
  locals: [
222
250
  ...params.map((p) => local(p.localId, p.name, p.type)),
223
- { ...local("ctx.0", "ctx", ctxType), boxed: true },
251
+ boxedLocal("ctx.0", "ctx", ctxType),
252
+ ...(withThis ? [boxedLocal("this.0", "this", DYN)] : []),
224
253
  local("n.0", "index", F64),
225
254
  local("f.0", "implementation", fn, true),
226
255
  local("i.0", "entry", F64, true),
@@ -242,13 +271,25 @@ function mockWrapperFactory(lowerer, ctxType, loc) {
242
271
  });
243
272
  lowerer.liftedFns.push({
244
273
  name,
245
- params: [{ localId: "ctx.0", name: "ctx", type: ctxType }],
274
+ params: [
275
+ { localId: "ctx.0", name: "ctx", type: ctxType },
276
+ ...(withThis ? [{ localId: "this.0", name: "this", type: DYN }] : []),
277
+ ],
246
278
  returnType: fn,
247
- locals: [{ ...local("ctx.0", "ctx", ctxType), boxed: true }],
279
+ locals: [
280
+ boxedLocal("ctx.0", "ctx", ctxType),
281
+ ...(withThis ? [boxedLocal("this.0", "this", DYN)] : []),
282
+ ],
248
283
  body: [
249
284
  {
250
285
  kind: "return",
251
- value: { kind: "closure", fnName: impl, captures: ["ctx.0"], type: fn, loc },
286
+ value: {
287
+ kind: "closure",
288
+ fnName: impl,
289
+ captures: withThis ? ["ctx.0", "this.0"] : ["ctx.0"],
290
+ type: fn,
291
+ loc,
292
+ },
252
293
  loc,
253
294
  },
254
295
  ],
@@ -256,6 +297,138 @@ function mockWrapperFactory(lowerer, ctxType, loc) {
256
297
  });
257
298
  });
258
299
  }
300
+ /** `%mock.restore.N(ctx)`: fn.mock.restore(). A method mock writes the
301
+ * original back to its object and keeps its implementation; a mock.fn mock
302
+ * goes back to its original implementation. */
303
+ function mockRestoreHelper(lowerer, ctxType, loc) {
304
+ const { fn, unmock } = mockContextFields(lowerer, ctxType);
305
+ return mockHelper(lowerer, ctxType, "restore", [], (ctx) => {
306
+ const unmockArray = () => recordGet(ctx(), "%unmock", unmock, loc);
307
+ return [
308
+ {
309
+ kind: "if",
310
+ cond: {
311
+ kind: "bin",
312
+ op: "===",
313
+ left: length(unmockArray(), loc),
314
+ right: numLit(0, loc),
315
+ type: BOOL,
316
+ loc,
317
+ },
318
+ then: [recordSet(ctx(), "%impl", recordGet(ctx(), "%original", fn, loc), loc)],
319
+ else_: [
320
+ {
321
+ kind: "exprStmt",
322
+ expr: {
323
+ kind: "callValue",
324
+ callee: {
325
+ kind: "arrayGet",
326
+ arr: unmockArray(),
327
+ index: numLit(0, loc),
328
+ type: RESTORE_FN,
329
+ loc,
330
+ },
331
+ args: [],
332
+ type: VOID,
333
+ loc,
334
+ },
335
+ loc,
336
+ },
337
+ ],
338
+ loc,
339
+ },
340
+ ];
341
+ }, loc);
342
+ }
343
+ /** `%mock.tracked.N(ctx)`: the closure a tracker keeps, which calls the
344
+ * mock's restore(). */
345
+ function mockTrackedFactory(lowerer, ctxType, loc) {
346
+ const restore = mockRestoreHelper(lowerer, ctxType, loc);
347
+ return liftOnce(lowerer, ctxType, "tracked", (name) => {
348
+ const impl = `${name}.impl`;
349
+ lowerer.liftedFns.push({
350
+ name: impl,
351
+ params: [],
352
+ returnType: VOID,
353
+ captures: [{ localId: "ctx.0", name: "ctx", type: ctxType }],
354
+ locals: [boxedLocal("ctx.0", "ctx", ctxType)],
355
+ body: [
356
+ {
357
+ kind: "exprStmt",
358
+ expr: {
359
+ kind: "call",
360
+ callee: restore,
361
+ args: [varRef("ctx.0", ctxType, loc)],
362
+ type: VOID,
363
+ loc,
364
+ },
365
+ loc,
366
+ },
367
+ { kind: "return", value: null, loc },
368
+ ],
369
+ loc,
370
+ });
371
+ lowerer.liftedFns.push({
372
+ name,
373
+ params: [{ localId: "ctx.0", name: "ctx", type: ctxType }],
374
+ returnType: RESTORE_FN,
375
+ locals: [boxedLocal("ctx.0", "ctx", ctxType)],
376
+ body: [
377
+ {
378
+ kind: "return",
379
+ value: { kind: "closure", fnName: impl, captures: ["ctx.0"], type: RESTORE_FN, loc },
380
+ loc,
381
+ },
382
+ ],
383
+ loc,
384
+ });
385
+ });
386
+ }
387
+ /** `%mock.unmock.N(object, original)`: the closure that writes `original`
388
+ * back to the object's field. */
389
+ function mockUnmockFactory(lowerer, ctxType, objType, field, loc) {
390
+ const { fn } = mockContextFields(lowerer, ctxType);
391
+ return liftOnce(lowerer, ctxType, "unmock", (name) => {
392
+ const impl = `${name}.impl`;
393
+ const captures = [
394
+ { localId: "obj.0", name: "object", type: objType },
395
+ { localId: "orig.0", name: "original", type: fn },
396
+ ];
397
+ const boxedLocals = captures.map((c) => boxedLocal(c.localId, c.name, c.type));
398
+ lowerer.liftedFns.push({
399
+ name: impl,
400
+ params: [],
401
+ returnType: VOID,
402
+ captures,
403
+ locals: boxedLocals,
404
+ body: [
405
+ recordSet(varRef("obj.0", objType, loc), field, varRef("orig.0", fn, loc), loc),
406
+ { kind: "return", value: null, loc },
407
+ ],
408
+ loc,
409
+ });
410
+ lowerer.liftedFns.push({
411
+ name,
412
+ params: captures,
413
+ returnType: RESTORE_FN,
414
+ locals: boxedLocals,
415
+ body: [
416
+ {
417
+ kind: "return",
418
+ value: {
419
+ kind: "closure",
420
+ fnName: impl,
421
+ captures: ["obj.0", "orig.0"],
422
+ type: RESTORE_FN,
423
+ loc,
424
+ },
425
+ loc,
426
+ },
427
+ ],
428
+ loc,
429
+ });
430
+ }, `${objType.shapeId}.${JSON.stringify(field)}`);
431
+ }
259
432
  /** A VOID helper over the context: `%mock.<role>.N(ctx, ...extra)`. */
260
433
  function mockHelper(lowerer, ctxType, role, extra, body, loc) {
261
434
  return liftOnce(lowerer, ctxType, role, (name) => {
@@ -277,8 +450,73 @@ function mockHelper(lowerer, ctxType, role, extra, body, loc) {
277
450
  });
278
451
  });
279
452
  }
453
+ /** Registers a mock's restore with its tracker. */
454
+ function trackMock(lowerer, tracker, ctxType, ctx, loc) {
455
+ const restore = {
456
+ kind: "call",
457
+ callee: mockTrackedFactory(lowerer, ctxType, loc),
458
+ args: [ctx],
459
+ type: RESTORE_FN,
460
+ loc,
461
+ };
462
+ return {
463
+ kind: "exprStmt",
464
+ expr: {
465
+ kind: "libCall",
466
+ fn: tracker ? "test.ctxMockTrack" : "test.mockTrack",
467
+ args: tracker ? [tracker, restore] : [restore],
468
+ type: VOID,
469
+ loc,
470
+ },
471
+ loc,
472
+ };
473
+ }
474
+ /** The context record literal of a new mock. */
475
+ function mockContextLiteral(ctxType, fields, implementation, original, unmock, loc) {
476
+ return {
477
+ kind: "recordLit",
478
+ fields: [
479
+ { name: "%impl", value: implementation },
480
+ { name: "%once", value: { kind: "arrayLit", elems: [], type: fields.once, loc } },
481
+ { name: "%original", value: original },
482
+ { name: "%unmock", value: { kind: "arrayLit", elems: unmock, type: fields.unmock, loc } },
483
+ { name: "calls", value: { kind: "arrayLit", elems: [], type: fields.calls, loc } },
484
+ ],
485
+ type: ctxType,
486
+ loc,
487
+ };
488
+ }
489
+ /** The Mock<F> record over a context: { %call: wrapper, mock: context }. */
490
+ function mockRecord(lowerer, mockType, ctxType, ctx, loc) {
491
+ const { fn } = mockContextFields(lowerer, ctxType);
492
+ return {
493
+ kind: "recordLit",
494
+ fields: [
495
+ {
496
+ name: "%call",
497
+ value: {
498
+ kind: "call",
499
+ callee: mockWrapperFactory(lowerer, ctxType, loc),
500
+ args: [ctx],
501
+ type: fn,
502
+ loc,
503
+ },
504
+ },
505
+ { name: "mock", value: ctx },
506
+ ],
507
+ type: mockType,
508
+ loc,
509
+ };
510
+ }
511
+ /** A union return type needs an undefined arm: the calls log records
512
+ * undefined for calls that throw. */
513
+ function requireUndefinedResultArm(lowerer, fields, call, what) {
514
+ if (fields.fn.ret.kind === "union" && typeKey(fields.result) !== typeKey(fields.fn.ret)) {
515
+ lowerer.noLowering(`${what} of a function returning '${lowerer.fmt(fields.fn.ret)}'`, call, "a union return type needs an undefined arm here (the calls log records undefined for calls that throw)");
516
+ }
517
+ }
280
518
  /** mock.fn(original, implementation?) and t.mock.fn(...). */
281
- export function lowerMockFn(lowerer, call, what) {
519
+ export function lowerMockFn(lowerer, call, what, tracker) {
282
520
  const loc = locOf(call);
283
521
  const mockType = lowerer.mapTypeOf(lowerer.typeOf(call));
284
522
  const shape = mockType?.kind === "record" ? lowerer.shapes.get(mockType.shapeId) : undefined;
@@ -289,12 +527,11 @@ export function lowerMockFn(lowerer, call, what) {
289
527
  !shape.fields.some((f) => f.name === "%call") ||
290
528
  !ctxType ||
291
529
  !isMockContextType(lowerer, ctxType)) {
292
- lowerer.noLowering(`${what} of this function type`, call, "mock functions lower for functions with fixed parameters, or a single rest array parameter");
293
- }
294
- const { fn, calls, once, result } = mockContextFields(lowerer, ctxType);
295
- if (fn.ret.kind === "union" && typeKey(result) !== typeKey(fn.ret)) {
296
- lowerer.noLowering(`${what} of a function returning '${lowerer.fmt(fn.ret)}'`, call, "a union return type needs an undefined arm here (the calls log records undefined for calls that throw)");
530
+ lowerer.noLowering(`${what} of this function type`, call, "mock functions lower for functions with fixed parameters, or a single rest array parameter, and an implementation of the same type");
297
531
  }
532
+ const fields = mockContextFields(lowerer, ctxType);
533
+ const { fn } = fields;
534
+ requireUndefinedResultArm(lowerer, fields, call, what);
298
535
  const args = call.arguments;
299
536
  if (args.length === 0 || args.length > 2 || args.some(ts.isSpreadElement)) {
300
537
  lowerer.noLowering(`${what} with ${args.length} arguments`, call, "the supported forms are mock.fn(original) and mock.fn(original, implementation); mock.fn() and mock options have no lowering");
@@ -311,48 +548,129 @@ export function lowerMockFn(lowerer, call, what) {
311
548
  ? lowerer.lowerExprExpecting(args[1], fn)
312
549
  : varRef(originalLocal.id, fn, loc);
313
550
  const ctxLocal = lowerer.declareHiddenLocal("%mockContext", ctxType);
551
+ const ctx = () => varRef(ctxLocal.id, ctxType, loc);
314
552
  stmts.push({
315
553
  kind: "varDecl",
316
554
  localId: ctxLocal.id,
317
- init: {
318
- kind: "recordLit",
319
- fields: [
320
- { name: "%impl", value: implementation },
321
- { name: "%once", value: { kind: "arrayLit", elems: [], type: once, loc } },
322
- { name: "%original", value: varRef(originalLocal.id, fn, loc) },
323
- { name: "calls", value: { kind: "arrayLit", elems: [], type: calls, loc } },
324
- ],
325
- type: ctxType,
326
- loc,
327
- },
555
+ init: mockContextLiteral(ctxType, fields, implementation, varRef(originalLocal.id, fn, loc), [], loc),
556
+ loc,
557
+ }, trackMock(lowerer, tracker, ctxType, ctx(), loc));
558
+ return {
559
+ kind: "seqExpr",
560
+ stmts,
561
+ result: mockRecord(lowerer, mockType, ctxType, ctx(), loc),
562
+ type: mockType,
563
+ loc,
564
+ };
565
+ }
566
+ const METHOD_HINT = "mock.method lowers for objects whose type maps to a record (object literals and interface-typed objects) and a function-valued field named by a string literal";
567
+ /** mock.method(object, methodName, implementation?) and t.mock.method. The
568
+ * field's function type F is the mock's type; an implementation must have
569
+ * the same type, unless the call's result is discarded. */
570
+ export function lowerMockMethod(lowerer, call, what, tracker) {
571
+ const loc = locOf(call);
572
+ const args = call.arguments;
573
+ if (args.length < 2 || args.length > 3 || args.some(ts.isSpreadElement)) {
574
+ lowerer.noLowering(`${what} with ${args.length} arguments`, call, "the supported forms are mock.method(object, methodName) and mock.method(object, methodName, implementation); mock options have no lowering");
575
+ }
576
+ const nameArg = args[1];
577
+ if (!ts.isStringLiteralLike(nameArg)) {
578
+ lowerer.noLowering(`${what} with a computed method name`, nameArg, METHOD_HINT);
579
+ }
580
+ const field = nameArg.text;
581
+ if (args.length === 3 &&
582
+ lowerer.checker.getCallSignatures(lowerer.typeOf(args[2])).length === 0) {
583
+ lowerer.noLowering(`${what} with an options object`, args[2], "mock options (times, getter and setter) have no lowering");
584
+ }
585
+ const objType = lowerer.mapTypeOf(lowerer.typeOf(args[0]));
586
+ const objShape = objType?.kind === "record" ? lowerer.shapes.get(objType.shapeId) : undefined;
587
+ const fn = objShape?.fields.find((f) => f.name === field)?.type;
588
+ if (!objType || !objShape || fn?.kind !== "func") {
589
+ const typeName = lowerer.typeOf(args[0]).getSymbol()?.name;
590
+ lowerer.noLowering(typeName && !typeName.startsWith("__")
591
+ ? `${what} on '${typeName}'`
592
+ : `${what} on this object`, args[0], METHOD_HINT);
593
+ }
594
+ const mockType = mockHybridType(fn, lowerer.typeCtx);
595
+ const ctxType = mockType?.kind === "record"
596
+ ? lowerer.shapes.get(mockType.shapeId)?.fields.find((f) => f.name === "mock")?.type
597
+ : undefined;
598
+ if (!mockType || !ctxType || !isMockContextType(lowerer, ctxType)) {
599
+ lowerer.noLowering(`${what} of a '${lowerer.fmt(fn)}' method`, call, "mock functions lower for functions with fixed parameters, or a single rest array parameter");
600
+ }
601
+ if (!resultIsDiscarded(call)) {
602
+ const resultType = lowerer.mapTypeOf(lowerer.typeOf(call));
603
+ if (!resultType || typeKey(resultType) !== typeKey(mockType)) {
604
+ lowerer.noLowering(`${what} with an implementation of another type`, args[2] ?? call, "give the implementation the method's parameter and return types, or discard the result");
605
+ }
606
+ }
607
+ const fields = mockContextFields(lowerer, ctxType);
608
+ requireUndefinedResultArm(lowerer, fields, call, what);
609
+ const stmts = [];
610
+ const objLocal = lowerer.declareHiddenLocal("%mockObject", objType);
611
+ const obj = () => varRef(objLocal.id, objType, loc);
612
+ stmts.push({ kind: "varDecl", localId: objLocal.id, init: lowerer.lowerExpr(args[0]), loc });
613
+ const originalLocal = lowerer.declareHiddenLocal("%mockOriginal", fn);
614
+ const original = () => varRef(originalLocal.id, fn, loc);
615
+ stmts.push({
616
+ kind: "varDecl",
617
+ localId: originalLocal.id,
618
+ init: recordGet(obj(), field, fn, loc),
328
619
  loc,
329
620
  });
330
- const factory = mockWrapperFactory(lowerer, ctxType, loc);
621
+ const implementation = args.length === 3 ? lowerer.lowerExprExpecting(args[2], fn) : original();
622
+ const unmock = {
623
+ kind: "call",
624
+ callee: mockUnmockFactory(lowerer, ctxType, objType, field, loc),
625
+ args: [obj(), original()],
626
+ type: RESTORE_FN,
627
+ loc,
628
+ };
629
+ const ctxLocal = lowerer.declareHiddenLocal("%mockContext", ctxType);
630
+ const ctx = () => varRef(ctxLocal.id, ctxType, loc);
631
+ stmts.push({
632
+ kind: "varDecl",
633
+ localId: ctxLocal.id,
634
+ init: mockContextLiteral(ctxType, fields, implementation, original(), [unmock], loc),
635
+ loc,
636
+ }, trackMock(lowerer, tracker, ctxType, ctx(), loc),
637
+ // The object's field: the wrapper that records the object as `this`.
638
+ recordSet(obj(), field, {
639
+ kind: "call",
640
+ callee: mockWrapperFactory(lowerer, ctxType, loc, true),
641
+ args: [ctx(), lowerer.coerceToExpected(obj(), DYN)],
642
+ type: fn,
643
+ loc,
644
+ }, loc));
331
645
  return {
332
646
  kind: "seqExpr",
333
647
  stmts,
334
- result: {
335
- kind: "recordLit",
336
- fields: [
337
- {
338
- name: "%call",
339
- value: {
340
- kind: "call",
341
- callee: factory,
342
- args: [varRef(ctxLocal.id, ctxType, loc)],
343
- type: fn,
344
- loc,
345
- },
346
- },
347
- { name: "mock", value: varRef(ctxLocal.id, ctxType, loc) },
348
- ],
349
- type: mockType,
350
- loc,
351
- },
648
+ result: mockRecord(lowerer, mockType, ctxType, ctx(), loc),
352
649
  type: mockType,
353
650
  loc,
354
651
  };
355
652
  }
653
+ /** The trackers' restoreAll() and reset(): `mock.restoreAll()`,
654
+ * `t.mock.reset()`. */
655
+ export function lowerMockTrackerCall(lowerer, call, member, tracker) {
656
+ if (call.arguments.length > 0) {
657
+ lowerer.noLowering(`MockTracker.${member} with ${call.arguments.length} arguments`, call);
658
+ }
659
+ const fn = tracker
660
+ ? member === "reset"
661
+ ? "test.ctxMockReset"
662
+ : "test.ctxMockRestoreAll"
663
+ : member === "reset"
664
+ ? "test.mockReset"
665
+ : "test.mockRestoreAll";
666
+ return {
667
+ kind: "libCall",
668
+ fn,
669
+ args: tracker ? [tracker] : [],
670
+ type: VOID,
671
+ loc: locOf(call),
672
+ };
673
+ }
356
674
  /** `fn.mock.calls`: a copy of the log, as Node's getter returns. Null for
357
675
  * other reads. */
358
676
  export function lowerMockContextProperty(lowerer, expr) {
@@ -492,11 +810,9 @@ export function lowerMockContextCall(lowerer, call, access) {
492
810
  ], loc);
493
811
  return helperCall(helper, []);
494
812
  }
495
- case "restore": {
813
+ case "restore":
496
814
  arity(0);
497
- const helper = mockHelper(lowerer, ctxType, "restore", [], (ctx) => [recordSet(ctx(), "%impl", recordGet(ctx(), "%original", fn, loc), loc)], loc);
498
- return helperCall(helper, []);
499
- }
815
+ return helperCall(mockRestoreHelper(lowerer, ctxType, loc), []);
500
816
  default:
501
817
  return lowerer.noLowering(`MockFunctionContext.${member}`, call, "calls, callCount, mockImplementation, mockImplementationOnce, resetCalls and restore are the supported mock context members");
502
818
  }