solve-engine 2.31.1 → 2.33.0

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 (226) hide show
  1. package/dist/{EngineError-CqGtaT_v.d.cts → EngineError-Bm4OYmw8.d.cts} +6 -0
  2. package/dist/{EngineError-CqGtaT_v.d.ts → EngineError-Bm4OYmw8.d.ts} +6 -0
  3. package/dist/{Lexer-CqFjYoRA.d.ts → Lexer-DPn5dfCH.d.ts} +1 -13
  4. package/dist/{Lexer-sCI05tqO.d.cts → Lexer-DaWkCu84.d.cts} +1 -13
  5. package/dist/{PackageCompatibility-phvSFP4f.d.ts → PackageCompatibility-CkzZfoJ3.d.ts} +1 -1
  6. package/dist/{PackageCompatibility-Bn-T_xKW.d.cts → PackageCompatibility-E_5GtcQW.d.cts} +1 -1
  7. package/dist/{PackageRegistry-C78jVkI9.d.ts → PackageRegistry-DSqic8kz.d.ts} +132 -23
  8. package/dist/{PackageRegistry-B-C1duZw.d.cts → PackageRegistry-js47hr28.d.cts} +132 -23
  9. package/dist/{Parselet-Dgymjxzd.d.ts → Parselet-CQjcHOKw.d.ts} +13 -6
  10. package/dist/{Parselet-DF3864la.d.cts → Parselet-s1sRRn8H.d.cts} +13 -6
  11. package/dist/{TokenNormalizer-Pe3_390t.d.cts → TokenNormalizer-D382VSYh.d.cts} +4 -1
  12. package/dist/{TokenNormalizer-IF7nPRMp.d.ts → TokenNormalizer-DAzPp-j1.d.ts} +4 -1
  13. package/dist/{VMBuiltins-BkKzhj6C.d.cts → VMBuiltins-JCavlQUj.d.cts} +53 -18
  14. package/dist/{VMBuiltins-Du9y8sEo.d.ts → VMBuiltins-qgzA6qGi.d.ts} +53 -18
  15. package/dist/{VMCheckpoints-WdUQrdc9.d.cts → VMCheckpoints-BxPzmdu0.d.cts} +2 -2
  16. package/dist/{VMCheckpoints-gvy_yxYh.d.ts → VMCheckpoints-DjjE92mf.d.ts} +2 -2
  17. package/dist/{Value-BYHw-x7q.d.cts → Value-2TIKi-YL.d.cts} +19 -0
  18. package/dist/{Value-BYHw-x7q.d.ts → Value-2TIKi-YL.d.ts} +19 -0
  19. package/dist/{WorkerError-DTrl3Jag.d.ts → WorkerError-BaN8_eok.d.ts} +1 -1
  20. package/dist/{WorkerError-CRoM8Ju1.d.cts → WorkerError-CexHHmbb.d.cts} +1 -1
  21. package/dist/{chunk-AGCNMEP2.cjs → chunk-3MG7VIPL.cjs} +2 -2
  22. package/dist/{chunk-AGCNMEP2.cjs.map → chunk-3MG7VIPL.cjs.map} +1 -1
  23. package/dist/chunk-4ASM522I.js +2 -0
  24. package/dist/chunk-4ASM522I.js.map +1 -0
  25. package/dist/chunk-4M3FZRGL.cjs +5 -0
  26. package/dist/chunk-4M3FZRGL.cjs.map +1 -0
  27. package/dist/{chunk-KH4QXKLT.js → chunk-4MD5L23F.js} +2 -2
  28. package/dist/{chunk-KH4QXKLT.js.map → chunk-4MD5L23F.js.map} +1 -1
  29. package/dist/{chunk-IQVSCL2R.js → chunk-4XWZXP6I.js} +3 -3
  30. package/dist/{chunk-IQVSCL2R.js.map → chunk-4XWZXP6I.js.map} +1 -1
  31. package/dist/{chunk-BSGZ3OEL.cjs → chunk-6DCSGINN.cjs} +3 -3
  32. package/dist/{chunk-BSGZ3OEL.cjs.map → chunk-6DCSGINN.cjs.map} +1 -1
  33. package/dist/{chunk-RELMEWY6.js → chunk-6G2NES2I.js} +2 -2
  34. package/dist/chunk-6G2NES2I.js.map +1 -0
  35. package/dist/{chunk-CDE2ZUGG.js → chunk-6NL7RBAG.js} +2 -2
  36. package/dist/{chunk-CDE2ZUGG.js.map → chunk-6NL7RBAG.js.map} +1 -1
  37. package/dist/{chunk-SUAGBRQ7.cjs → chunk-6SYU4MH7.cjs} +2 -2
  38. package/dist/chunk-6SYU4MH7.cjs.map +1 -0
  39. package/dist/chunk-72J5V7SN.cjs +2 -0
  40. package/dist/chunk-72J5V7SN.cjs.map +1 -0
  41. package/dist/chunk-7CRVRPV7.cjs +3 -0
  42. package/dist/chunk-7CRVRPV7.cjs.map +1 -0
  43. package/dist/chunk-ADK7LGYN.js +5 -0
  44. package/dist/chunk-ADK7LGYN.js.map +1 -0
  45. package/dist/chunk-APYRNAU2.js +2 -0
  46. package/dist/chunk-APYRNAU2.js.map +1 -0
  47. package/dist/{chunk-KBRSNJMQ.js → chunk-D55NMAGM.js} +3 -3
  48. package/dist/{chunk-KBRSNJMQ.js.map → chunk-D55NMAGM.js.map} +1 -1
  49. package/dist/chunk-DB5ISONG.js +2 -0
  50. package/dist/chunk-DB5ISONG.js.map +1 -0
  51. package/dist/chunk-EOKHRS2T.js +2 -0
  52. package/dist/chunk-EOKHRS2T.js.map +1 -0
  53. package/dist/{chunk-NQFCXLEF.js → chunk-EOO6M65F.js} +2 -2
  54. package/dist/{chunk-NQFCXLEF.js.map → chunk-EOO6M65F.js.map} +1 -1
  55. package/dist/{chunk-A764BY7L.cjs → chunk-EQNKDTMX.cjs} +2 -2
  56. package/dist/{chunk-A764BY7L.cjs.map → chunk-EQNKDTMX.cjs.map} +1 -1
  57. package/dist/chunk-FESR6PZI.cjs +2 -0
  58. package/dist/chunk-FESR6PZI.cjs.map +1 -0
  59. package/dist/chunk-G5TZ6TDA.js +2 -0
  60. package/dist/chunk-G5TZ6TDA.js.map +1 -0
  61. package/dist/chunk-GDLYXRMA.cjs +2 -0
  62. package/dist/chunk-GDLYXRMA.cjs.map +1 -0
  63. package/dist/chunk-HOU7QTE7.js +3 -0
  64. package/dist/chunk-HOU7QTE7.js.map +1 -0
  65. package/dist/{chunk-VYQNPCM5.cjs → chunk-HPV4CKCC.cjs} +2 -2
  66. package/dist/{chunk-VYQNPCM5.cjs.map → chunk-HPV4CKCC.cjs.map} +1 -1
  67. package/dist/{chunk-7DJYS5PO.cjs → chunk-HSTGWWU2.cjs} +2 -2
  68. package/dist/{chunk-7DJYS5PO.cjs.map → chunk-HSTGWWU2.cjs.map} +1 -1
  69. package/dist/{chunk-OE2DBN4K.js → chunk-INMJ7ZXL.js} +2 -2
  70. package/dist/chunk-INMJ7ZXL.js.map +1 -0
  71. package/dist/{chunk-TP5EQCGH.js → chunk-J3YC3IQD.js} +2 -2
  72. package/dist/{chunk-TP5EQCGH.js.map → chunk-J3YC3IQD.js.map} +1 -1
  73. package/dist/{chunk-5AKT36UK.cjs → chunk-K3PZ66XR.cjs} +2 -2
  74. package/dist/{chunk-5AKT36UK.cjs.map → chunk-K3PZ66XR.cjs.map} +1 -1
  75. package/dist/chunk-LI6LYJDA.cjs +2 -0
  76. package/dist/chunk-LI6LYJDA.cjs.map +1 -0
  77. package/dist/{chunk-WQGHJAW2.cjs → chunk-M4UC2PB6.cjs} +2 -2
  78. package/dist/{chunk-WQGHJAW2.cjs.map → chunk-M4UC2PB6.cjs.map} +1 -1
  79. package/dist/chunk-O7HF345B.js +2 -0
  80. package/dist/chunk-O7HF345B.js.map +1 -0
  81. package/dist/{chunk-CM2WM5CM.cjs → chunk-OBZJKZ2F.cjs} +2 -2
  82. package/dist/{chunk-CM2WM5CM.cjs.map → chunk-OBZJKZ2F.cjs.map} +1 -1
  83. package/dist/{chunk-Q7TBBV62.cjs → chunk-P5YWBIIU.cjs} +2 -2
  84. package/dist/chunk-P5YWBIIU.cjs.map +1 -0
  85. package/dist/chunk-PICFFFJV.js +3 -0
  86. package/dist/chunk-PICFFFJV.js.map +1 -0
  87. package/dist/{chunk-P43SV4NJ.cjs → chunk-QOOTRUY7.cjs} +3 -3
  88. package/dist/{chunk-P43SV4NJ.cjs.map → chunk-QOOTRUY7.cjs.map} +1 -1
  89. package/dist/chunk-R3W53ZMP.cjs +2 -0
  90. package/dist/chunk-R3W53ZMP.cjs.map +1 -0
  91. package/dist/chunk-RMDCGYZM.js +2 -0
  92. package/dist/chunk-RMDCGYZM.js.map +1 -0
  93. package/dist/{chunk-CB3EXUM2.js → chunk-RU3KGJRA.js} +2 -2
  94. package/dist/chunk-RU3KGJRA.js.map +1 -0
  95. package/dist/chunk-S3SPDK6N.cjs +2 -0
  96. package/dist/chunk-S3SPDK6N.cjs.map +1 -0
  97. package/dist/chunk-SF5QVUEI.cjs +3 -0
  98. package/dist/chunk-SF5QVUEI.cjs.map +1 -0
  99. package/dist/{chunk-FXB5GCBT.js → chunk-TJKN466F.js} +2 -2
  100. package/dist/{chunk-FXB5GCBT.js.map → chunk-TJKN466F.js.map} +1 -1
  101. package/dist/{chunk-VLX7ZVK4.js → chunk-U5MESNRT.js} +2 -2
  102. package/dist/{chunk-VLX7ZVK4.js.map → chunk-U5MESNRT.js.map} +1 -1
  103. package/dist/{chunk-YWF6C2IO.cjs → chunk-WFT3XUSH.cjs} +2 -2
  104. package/dist/{chunk-YWF6C2IO.cjs.map → chunk-WFT3XUSH.cjs.map} +1 -1
  105. package/dist/{chunk-3ZGFAE3Q.js → chunk-X2GQAKL2.js} +2 -2
  106. package/dist/{chunk-3ZGFAE3Q.js.map → chunk-X2GQAKL2.js.map} +1 -1
  107. package/dist/{chunk-G3POUURF.js → chunk-YID47OPR.js} +2 -2
  108. package/dist/{chunk-G3POUURF.js.map → chunk-YID47OPR.js.map} +1 -1
  109. package/dist/chunk-YV4GDW5A.cjs +2 -0
  110. package/dist/chunk-YV4GDW5A.cjs.map +1 -0
  111. package/dist/chunk-ZSXQP7PD.cjs +2 -0
  112. package/dist/chunk-ZSXQP7PD.cjs.map +1 -0
  113. package/dist/constants.cjs +1 -1
  114. package/dist/constants.js +1 -1
  115. package/dist/engine.cjs +1 -1
  116. package/dist/engine.d.cts +10 -10
  117. package/dist/engine.d.ts +10 -10
  118. package/dist/engine.js +1 -1
  119. package/dist/engine.worker.cjs +1 -1
  120. package/dist/engine.worker.cjs.map +1 -1
  121. package/dist/engine.worker.js +1 -1
  122. package/dist/engine.worker.js.map +1 -1
  123. package/dist/errors.cjs +1 -1
  124. package/dist/errors.d.cts +3 -3
  125. package/dist/errors.d.ts +3 -3
  126. package/dist/errors.js +1 -1
  127. package/dist/format.cjs +1 -1
  128. package/dist/format.d.cts +1 -1
  129. package/dist/format.d.ts +1 -1
  130. package/dist/format.js +1 -1
  131. package/dist/index.cjs +1 -1
  132. package/dist/index.cjs.map +1 -1
  133. package/dist/index.d.cts +10 -10
  134. package/dist/index.d.ts +10 -10
  135. package/dist/index.js +1 -1
  136. package/dist/index.js.map +1 -1
  137. package/dist/language.d.cts +9 -9
  138. package/dist/language.d.ts +9 -9
  139. package/dist/lexer.cjs +1 -1
  140. package/dist/lexer.d.cts +3 -3
  141. package/dist/lexer.d.ts +3 -3
  142. package/dist/lexer.js +1 -1
  143. package/dist/normalizer.cjs +1 -1
  144. package/dist/normalizer.d.cts +2 -2
  145. package/dist/normalizer.d.ts +2 -2
  146. package/dist/normalizer.js +1 -1
  147. package/dist/packages.cjs +1 -1
  148. package/dist/packages.d.cts +8 -8
  149. package/dist/packages.d.ts +8 -8
  150. package/dist/packages.js +1 -1
  151. package/dist/parser.cjs +1 -1
  152. package/dist/parser.d.cts +3 -3
  153. package/dist/parser.d.ts +3 -3
  154. package/dist/parser.js +1 -1
  155. package/dist/{pipeline-BYkKNpql.d.cts → pipeline-Bum6y1B9.d.cts} +1 -1
  156. package/dist/{pipeline-Cl7KW8CB.d.ts → pipeline-DOo3KHaq.d.ts} +1 -1
  157. package/dist/resolvers.cjs +1 -1
  158. package/dist/resolvers.d.cts +69 -3
  159. package/dist/resolvers.d.ts +69 -3
  160. package/dist/resolvers.js +1 -1
  161. package/dist/temporal.cjs +1 -1
  162. package/dist/temporal.js +1 -1
  163. package/dist/testing.cjs +2 -2
  164. package/dist/testing.cjs.map +1 -1
  165. package/dist/testing.d.cts +9 -9
  166. package/dist/testing.d.ts +9 -9
  167. package/dist/testing.js +1 -1
  168. package/dist/testing.js.map +1 -1
  169. package/dist/uom.cjs +1 -1
  170. package/dist/uom.d.cts +35 -2
  171. package/dist/uom.d.ts +35 -2
  172. package/dist/uom.js +1 -1
  173. package/dist/vm.cjs +1 -1
  174. package/dist/vm.d.cts +6 -6
  175. package/dist/vm.d.ts +6 -6
  176. package/dist/vm.js +1 -1
  177. package/dist/worker.cjs +2 -2
  178. package/dist/worker.cjs.map +1 -1
  179. package/dist/worker.d.cts +9 -9
  180. package/dist/worker.d.ts +9 -9
  181. package/dist/worker.js +1 -1
  182. package/dist/worker.js.map +1 -1
  183. package/package.json +1 -1
  184. package/dist/chunk-4DR5RBHQ.cjs +0 -2
  185. package/dist/chunk-4DR5RBHQ.cjs.map +0 -1
  186. package/dist/chunk-6LA7HC46.js +0 -3
  187. package/dist/chunk-6LA7HC46.js.map +0 -1
  188. package/dist/chunk-A755LVPT.cjs +0 -2
  189. package/dist/chunk-A755LVPT.cjs.map +0 -1
  190. package/dist/chunk-AF6NDOIE.js +0 -2
  191. package/dist/chunk-AF6NDOIE.js.map +0 -1
  192. package/dist/chunk-B2NL65FI.js +0 -2
  193. package/dist/chunk-B2NL65FI.js.map +0 -1
  194. package/dist/chunk-CB3EXUM2.js.map +0 -1
  195. package/dist/chunk-DUFEONVN.cjs +0 -3
  196. package/dist/chunk-DUFEONVN.cjs.map +0 -1
  197. package/dist/chunk-IJHL3LMH.js +0 -2
  198. package/dist/chunk-IJHL3LMH.js.map +0 -1
  199. package/dist/chunk-LCYQQFUH.cjs +0 -2
  200. package/dist/chunk-LCYQQFUH.cjs.map +0 -1
  201. package/dist/chunk-LP3JYC3A.js +0 -2
  202. package/dist/chunk-LP3JYC3A.js.map +0 -1
  203. package/dist/chunk-MDTIL3UT.cjs +0 -5
  204. package/dist/chunk-MDTIL3UT.cjs.map +0 -1
  205. package/dist/chunk-MZQ3ED6J.cjs +0 -3
  206. package/dist/chunk-MZQ3ED6J.cjs.map +0 -1
  207. package/dist/chunk-OE2DBN4K.js.map +0 -1
  208. package/dist/chunk-OM7NOHJF.cjs +0 -2
  209. package/dist/chunk-OM7NOHJF.cjs.map +0 -1
  210. package/dist/chunk-PTXUWGRR.js +0 -3
  211. package/dist/chunk-PTXUWGRR.js.map +0 -1
  212. package/dist/chunk-Q7TBBV62.cjs.map +0 -1
  213. package/dist/chunk-RELMEWY6.js.map +0 -1
  214. package/dist/chunk-SFM4XFGJ.js +0 -2
  215. package/dist/chunk-SFM4XFGJ.js.map +0 -1
  216. package/dist/chunk-SNYFNARL.js +0 -5
  217. package/dist/chunk-SNYFNARL.js.map +0 -1
  218. package/dist/chunk-SUAGBRQ7.cjs.map +0 -1
  219. package/dist/chunk-UNKZ5XRC.cjs +0 -2
  220. package/dist/chunk-UNKZ5XRC.cjs.map +0 -1
  221. package/dist/chunk-WU7SBKVU.cjs +0 -2
  222. package/dist/chunk-WU7SBKVU.cjs.map +0 -1
  223. package/dist/chunk-X5K72MBV.js +0 -2
  224. package/dist/chunk-X5K72MBV.js.map +0 -1
  225. package/dist/chunk-ZVPZQ66D.cjs +0 -2
  226. package/dist/chunk-ZVPZQ66D.cjs.map +0 -1
package/dist/testing.d.ts CHANGED
@@ -1,17 +1,17 @@
1
- import { I as IEnginePackage, E as ExpressionEngine } from './PackageRegistry-C78jVkI9.js';
2
- import { V as Value } from './Value-BYHw-x7q.js';
3
- import { E as EngineError } from './EngineError-CqGtaT_v.js';
4
- import { C as CompatibilityReport } from './PackageCompatibility-phvSFP4f.js';
5
- import './Parselet-Dgymjxzd.js';
1
+ import { I as IEnginePackage, E as ExpressionEngine } from './PackageRegistry-DSqic8kz.js';
2
+ import { V as Value } from './Value-2TIKi-YL.js';
3
+ import { E as EngineError } from './EngineError-Bm4OYmw8.js';
4
+ import { C as CompatibilityReport } from './PackageCompatibility-CkzZfoJ3.js';
5
+ import './Parselet-CQjcHOKw.js';
6
6
  import './BytecodeBuilder-DSWKZi4f.js';
7
7
  import './Token-D8f7yaz1.js';
8
- import './pipeline-Cl7KW8CB.js';
8
+ import './pipeline-DOo3KHaq.js';
9
9
  import './CalendarBackend-MdS3Bb4P.js';
10
- import './Lexer-CqFjYoRA.js';
10
+ import './Lexer-DPn5dfCH.js';
11
11
  import './resolvers.js';
12
12
  import '@tanstack/query-core';
13
- import './TokenNormalizer-IF7nPRMp.js';
14
- import './VMBuiltins-Du9y8sEo.js';
13
+ import './TokenNormalizer-DAzPp-j1.js';
14
+ import './VMBuiltins-qgzA6qGi.js';
15
15
  import './Configuration-BxriK9Kw.js';
16
16
 
17
17
  /**
package/dist/testing.js CHANGED
@@ -1,4 +1,4 @@
1
- import {o,a,b}from'./chunk-SNYFNARL.js';import'./chunk-CB3EXUM2.js';import'./chunk-2RWAXT6O.js';import'./chunk-IJHL3LMH.js';import'./chunk-MIQBJGGR.js';import'./chunk-AF6NDOIE.js';import'./chunk-JP4JMQOG.js';import'./chunk-IQVSCL2R.js';import'./chunk-XEIDV5JP.js';import {z}from'./chunk-6LA7HC46.js';import'./chunk-SFM4XFGJ.js';import'./chunk-FXB5GCBT.js';import'./chunk-VLX7ZVK4.js';import'./chunk-B2NL65FI.js';import'./chunk-76F3LCIL.js';import'./chunk-TCZSPH4A.js';import'./chunk-OE2DBN4K.js';import'./chunk-3ZGFAE3Q.js';import'./chunk-PTXUWGRR.js';import'./chunk-TZYMXNIB.js';import'./chunk-HFKDWQUL.js';import'./chunk-5TCSFTZD.js';import'./chunk-KH4QXKLT.js';import'./chunk-NQFCXLEF.js';import'./chunk-J4K72CQN.js';import {m}from'./chunk-X5K72MBV.js';import'./chunk-BWTVJD5L.js';import {a as a$1}from'./chunk-TP5EQCGH.js';import'./chunk-CDE2ZUGG.js';import'./chunk-JPFCXLJV.js';import'./chunk-LP3JYC3A.js';import'./chunk-FAO6DQ74.js';import'./chunk-LHLW7JLS.js';import'./chunk-CHVGFTO3.js';import'./chunk-PRSXXDTA.js';import {b as b$1}from'./chunk-RELMEWY6.js';var i=class o extends Error{constructor(t){super(t.message),this.name="ExpectationError",this.code=t.code,this.expected=t.expected,this.actual=t.actual,Object.setPrototypeOf(this,o.prototype);}};function V(o$1=[],t={}){let{locale:e="en",includeBuiltins:r=true}=t,s=new o({locale:e,packages:r?z:[]});for(let a of o$1)s.registerPackage(a);return s}function v(o,t){try{let e=o.evaluateExpression(t);return e.isError()?{status:"error",code:e.errorCode??"",message:e.errorMessage??"",source:e}:e.isPending()?{status:"pending",value:e}:{status:"value",value:e}}catch(e){if(e instanceof b$1)return {status:"error",code:e.code,message:e.message,source:e};let r=e instanceof Error?e.message:String(e);return {status:"error",code:"UNKNOWN_ERROR",message:r,source:new m(13,"UNKNOWN_ERROR",r)}}}function x(o,t){if(Object.is(o,t))return true;if(!Number.isFinite(o)||!Number.isFinite(t))return false;let e=1e-9*Math.max(1,Math.abs(o),Math.abs(t));return Math.abs(o-t)<=e}function l(o){return o.type===3?JSON.stringify(o.value):o.type===6&&typeof o.unit=="string"?`${String(o.value)} ${o.unit}`:String(o.value)}function n(o){switch(o.status){case "value":return l(o.value);case "pending":return "a pending async value";case "error":return `an error (${o.code}: ${o.message})`}}var d=class{constructor(t,e){this.expression=t;this.outcome=e;}get value(){if(this.outcome.status==="error")throw new i({code:"EXPECTED_VALUE",message:`Expected "${this.expression}" to evaluate, but it failed with ${n(this.outcome)}.`,expected:"a resolved value",actual:n(this.outcome)});return this.outcome.value}toEvaluate(){if(this.outcome.status!=="value")throw new i({code:"EXPECTED_EVALUATE",message:`Expected "${this.expression}" to evaluate to a value, but got ${n(this.outcome)}.`,expected:"a resolved value",actual:n(this.outcome)});return this}toEqual(t,e){if(this.outcome.status!=="value")throw new i({code:"EXPECTED_EQUAL",message:`Expected "${this.expression}" to equal ${c(t,e)}, but got ${n(this.outcome)}.`,expected:c(t,e),actual:n(this.outcome)});let r=this.outcome.value,s;if(typeof t=="number"?s=x(r.toNumber(),t):typeof t=="boolean"?s=r.type===10&&r.value===t:s=C(r)===t,!s)throw new i({code:"EXPECTED_EQUAL",message:`Expected "${this.expression}" to equal ${c(t,e)}, but it was ${l(r)}.`,expected:c(t,e),actual:l(r)});if(e!==void 0&&r.unit!==e)throw new i({code:"EXPECTED_UNIT",message:`Expected "${this.expression}" to carry the unit "${e}", but it was ${r.unit===void 0?"unitless":`"${r.unit}"`}.`,expected:`unit "${e}"`,actual:r.unit===void 0?"no unit":`unit "${r.unit}"`});return this}toBeError(){if(this.outcome.status!=="error")throw new i({code:"EXPECTED_ERROR",message:`Expected "${this.expression}" to fail, but it produced ${n(this.outcome)}.`,expected:"an error",actual:n(this.outcome)});return this}toFailWith(t){if(this.outcome.status!=="error")throw new i({code:"EXPECTED_FAIL_WITH",message:`Expected "${this.expression}" to fail with "${t}", but it produced ${n(this.outcome)}.`,expected:`error code "${t}"`,actual:n(this.outcome)});if(this.outcome.code!==t)throw new i({code:"EXPECTED_FAIL_WITH",message:`Expected "${this.expression}" to fail with "${t}", but it failed with "${this.outcome.code}" (${this.outcome.message}).`,expected:`error code "${t}"`,actual:`error code "${this.outcome.code}"`});return this}toBePending(){if(this.outcome.status!=="pending")throw new i({code:"EXPECTED_PENDING",message:`Expected "${this.expression}" to be pending, but got ${n(this.outcome)}.`,expected:"a pending async value",actual:n(this.outcome)});return this}};function c(o,t){let e=typeof o=="string"?JSON.stringify(o):String(o);return t===void 0?e:`${e} ${t}`}function C(o){return String(o.value)}function D(o,t){return new d(t,v(o,t))}var O=["a","an","and","or","but","if","then","the","this","that","these","those","in","on","at","to","of","for","from","with","by","as","per","into","over","is","are","was","were","be","been","being","do","does","did","have","has","had","will","would","can","could","should","may","might","must","price","cost","value","total","sum","count","rate","amount","number","time","date","day","week","month","year","hour","minute","second","add","buy","sell","hold","make","take","give","get","set","run","up","down","out","off","all","some","any","no","not","more","less","one","two","three","first","last","next","each","every","here","there"],$=["error","warning","info"];function k(o){let t=[],e=o.lexerVocabulary;if(e?.keywords)for(let[r,s]of Object.entries(e.keywords))t.push({word:r,via:"keyword",tokenType:s});if(e?.units)for(let r of e.units)t.push({word:r,via:"unit"});if(e?.operators)for(let[r,s]of Object.entries(e.operators))t.push({word:r,via:"operator",tokenType:s});if(o.phrases)for(let[r,s]of Object.entries(o.phrases))r.includes(" ")||t.push({word:r,via:"phrase",tokenType:s});return t}var p=class{constructor(t){this.pkg=t;}notToShadow(t=O){let e=new Set(t.map(s=>s.toLowerCase())),r=k(this.pkg).filter(s=>e.has(s.word.toLowerCase()));if(r.length>0){let s=r.map(a=>`"${a.word}" (${a.via})`).join(", ");throw new i({code:"PACKAGE_SHADOWS_PROSE",message:`Package "${this.pkg.name}" claims prose word(s) as syntax: ${s}. A word that is also ordinary English turns prose into arithmetic; prefer a multi-word phrase or a form that requires a parenthesis.`,expected:"no prose words claimed as syntax",actual:s})}return r}notToCollideWith(t,e="error"){let r=a(this.pkg,t),s=$.indexOf(e),a$1=r.conflicts.filter(u=>$.indexOf(u.severity)<=s);if(a$1.length>0){let u=a$1.map(g=>`[${g.severity}] ${g.detail}`).join(`
1
+ import {o,a,b}from'./chunk-ADK7LGYN.js';import'./chunk-RU3KGJRA.js';import'./chunk-2RWAXT6O.js';import'./chunk-RMDCGYZM.js';import'./chunk-MIQBJGGR.js';import'./chunk-4ASM522I.js';import'./chunk-JP4JMQOG.js';import'./chunk-4XWZXP6I.js';import'./chunk-XEIDV5JP.js';import {z}from'./chunk-HOU7QTE7.js';import'./chunk-G5TZ6TDA.js';import'./chunk-TJKN466F.js';import'./chunk-U5MESNRT.js';import'./chunk-DB5ISONG.js';import'./chunk-76F3LCIL.js';import'./chunk-EOKHRS2T.js';import'./chunk-TCZSPH4A.js';import'./chunk-INMJ7ZXL.js';import'./chunk-X2GQAKL2.js';import'./chunk-PICFFFJV.js';import'./chunk-TZYMXNIB.js';import'./chunk-HFKDWQUL.js';import'./chunk-5TCSFTZD.js';import'./chunk-4MD5L23F.js';import'./chunk-EOO6M65F.js';import'./chunk-J4K72CQN.js';import {m}from'./chunk-O7HF345B.js';import'./chunk-BWTVJD5L.js';import {a as a$1}from'./chunk-J3YC3IQD.js';import'./chunk-6NL7RBAG.js';import'./chunk-JPFCXLJV.js';import'./chunk-APYRNAU2.js';import'./chunk-FAO6DQ74.js';import'./chunk-LHLW7JLS.js';import'./chunk-CHVGFTO3.js';import'./chunk-PRSXXDTA.js';import {b as b$1}from'./chunk-6G2NES2I.js';var i=class o extends Error{constructor(t){super(t.message),this.name="ExpectationError",this.code=t.code,this.expected=t.expected,this.actual=t.actual,Object.setPrototypeOf(this,o.prototype);}};function V(o$1=[],t={}){let{locale:e="en",includeBuiltins:r=true}=t,s=new o({locale:e,packages:r?z:[]});for(let a of o$1)s.registerPackage(a);return s}function v(o,t){try{let e=o.evaluateExpression(t);return e.isError()?{status:"error",code:e.errorCode??"",message:e.errorMessage??"",source:e}:e.isPending()?{status:"pending",value:e}:{status:"value",value:e}}catch(e){if(e instanceof b$1)return {status:"error",code:e.code,message:e.message,source:e};let r=e instanceof Error?e.message:String(e);return {status:"error",code:"UNKNOWN_ERROR",message:r,source:new m(13,"UNKNOWN_ERROR",r)}}}function x(o,t){if(Object.is(o,t))return true;if(!Number.isFinite(o)||!Number.isFinite(t))return false;let e=1e-9*Math.max(1,Math.abs(o),Math.abs(t));return Math.abs(o-t)<=e}function l(o){return o.type===3?JSON.stringify(o.value):o.type===6&&typeof o.unit=="string"?`${String(o.value)} ${o.unit}`:String(o.value)}function n(o){switch(o.status){case "value":return l(o.value);case "pending":return "a pending async value";case "error":return `an error (${o.code}: ${o.message})`}}var d=class{constructor(t,e){this.expression=t;this.outcome=e;}get value(){if(this.outcome.status==="error")throw new i({code:"EXPECTED_VALUE",message:`Expected "${this.expression}" to evaluate, but it failed with ${n(this.outcome)}.`,expected:"a resolved value",actual:n(this.outcome)});return this.outcome.value}toEvaluate(){if(this.outcome.status!=="value")throw new i({code:"EXPECTED_EVALUATE",message:`Expected "${this.expression}" to evaluate to a value, but got ${n(this.outcome)}.`,expected:"a resolved value",actual:n(this.outcome)});return this}toEqual(t,e){if(this.outcome.status!=="value")throw new i({code:"EXPECTED_EQUAL",message:`Expected "${this.expression}" to equal ${c(t,e)}, but got ${n(this.outcome)}.`,expected:c(t,e),actual:n(this.outcome)});let r=this.outcome.value,s;if(typeof t=="number"?s=x(r.toNumber(),t):typeof t=="boolean"?s=r.type===10&&r.value===t:s=C(r)===t,!s)throw new i({code:"EXPECTED_EQUAL",message:`Expected "${this.expression}" to equal ${c(t,e)}, but it was ${l(r)}.`,expected:c(t,e),actual:l(r)});if(e!==void 0&&r.unit!==e)throw new i({code:"EXPECTED_UNIT",message:`Expected "${this.expression}" to carry the unit "${e}", but it was ${r.unit===void 0?"unitless":`"${r.unit}"`}.`,expected:`unit "${e}"`,actual:r.unit===void 0?"no unit":`unit "${r.unit}"`});return this}toBeError(){if(this.outcome.status!=="error")throw new i({code:"EXPECTED_ERROR",message:`Expected "${this.expression}" to fail, but it produced ${n(this.outcome)}.`,expected:"an error",actual:n(this.outcome)});return this}toFailWith(t){if(this.outcome.status!=="error")throw new i({code:"EXPECTED_FAIL_WITH",message:`Expected "${this.expression}" to fail with "${t}", but it produced ${n(this.outcome)}.`,expected:`error code "${t}"`,actual:n(this.outcome)});if(this.outcome.code!==t)throw new i({code:"EXPECTED_FAIL_WITH",message:`Expected "${this.expression}" to fail with "${t}", but it failed with "${this.outcome.code}" (${this.outcome.message}).`,expected:`error code "${t}"`,actual:`error code "${this.outcome.code}"`});return this}toBePending(){if(this.outcome.status!=="pending")throw new i({code:"EXPECTED_PENDING",message:`Expected "${this.expression}" to be pending, but got ${n(this.outcome)}.`,expected:"a pending async value",actual:n(this.outcome)});return this}};function c(o,t){let e=typeof o=="string"?JSON.stringify(o):String(o);return t===void 0?e:`${e} ${t}`}function C(o){return String(o.value)}function D(o,t){return new d(t,v(o,t))}var O=["a","an","and","or","but","if","then","the","this","that","these","those","in","on","at","to","of","for","from","with","by","as","per","into","over","is","are","was","were","be","been","being","do","does","did","have","has","had","will","would","can","could","should","may","might","must","price","cost","value","total","sum","count","rate","amount","number","time","date","day","week","month","year","hour","minute","second","add","buy","sell","hold","make","take","give","get","set","run","up","down","out","off","all","some","any","no","not","more","less","one","two","three","first","last","next","each","every","here","there"],$=["error","warning","info"];function k(o){let t=[],e=o.lexerVocabulary;if(e?.keywords)for(let[r,s]of Object.entries(e.keywords))t.push({word:r,via:"keyword",tokenType:s});if(e?.units)for(let r of e.units)t.push({word:r,via:"unit"});if(e?.operators)for(let[r,s]of Object.entries(e.operators))t.push({word:r,via:"operator",tokenType:s});if(o.phrases)for(let[r,s]of Object.entries(o.phrases))r.includes(" ")||t.push({word:r,via:"phrase",tokenType:s});return t}var p=class{constructor(t){this.pkg=t;}notToShadow(t=O){let e=new Set(t.map(s=>s.toLowerCase())),r=k(this.pkg).filter(s=>e.has(s.word.toLowerCase()));if(r.length>0){let s=r.map(a=>`"${a.word}" (${a.via})`).join(", ");throw new i({code:"PACKAGE_SHADOWS_PROSE",message:`Package "${this.pkg.name}" claims prose word(s) as syntax: ${s}. A word that is also ordinary English turns prose into arithmetic; prefer a multi-word phrase or a form that requires a parenthesis.`,expected:"no prose words claimed as syntax",actual:s})}return r}notToCollideWith(t,e="error"){let r=a(this.pkg,t),s=$.indexOf(e),a$1=r.conflicts.filter(u=>$.indexOf(u.severity)<=s);if(a$1.length>0){let u=a$1.map(g=>`[${g.severity}] ${g.detail}`).join(`
2
2
  `);throw new i({code:"PACKAGE_VOCABULARY_COLLISION",message:`Package "${this.pkg.name}" collides with another package:
3
3
  ${u}`,expected:`no conflicts at or above "${e}" severity`,actual:`${a$1.length} conflict(s)`})}return r}toDeclareCompatibleEngineVersion(t=a$1){let e=b(this.pkg,t);if(!e.compatible){let r=e.reason==="invalid-range"?`its range "${e.declaredRange}" is not valid semver`:`its range "${e.declaredRange}" is not satisfied by engine version "${e.engineVersion}"`;throw new i({code:"PACKAGE_ENGINE_VERSION_INCOMPATIBLE",message:`Package "${this.pkg.name}" declares an engineVersion that will be rejected at registration: ${r}.`,expected:`an engineVersion satisfied by "${t}"`,actual:`"${e.declaredRange}"`})}return this}};function L(o){return new p(o)}export{O as COMMON_PROSE_WORDS,i as ExpectationError,d as ExpressionAssertion,p as PackageAssertion,V as createTestEngine,D as expectExpression,L as expectPackage};//# sourceMappingURL=testing.js.map
4
4
  //# sourceMappingURL=testing.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/testing/index.ts"],"names":["ExpectationError","_ExpectationError","init","createTestEngine","packages","options","locale","includeBuiltins","engine","ExpressionEngine","BUILTIN_PACKAGES","pkg","evaluate","expression","value","error","EngineError","message","Value","numbersEqual","a","b","epsilon","describeValue","describeOutcome","outcome","ExpressionAssertion","expected","unit","describeExpected","matches","valueToComparableString","code","base","expectExpression","COMMON_PROSE_WORDS","SEVERITY_ORDER","claimedWords","claimed","vocab","word","tokenType","phrase","PackageAssertion","words","prose","w","shadowed","c","list","s","others","strictness","report","checkPackageCompatibility","threshold","failing","engineVersion","ENGINE_VERSION","result","checkEngineVersionCompatibility","detail","expectPackage"],"mappings":"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","file":"testing.js","sourcesContent":["/**\n * A test kit for package authors, the supported way to test a package by the\n * expressions it enables rather than by the opcodes it emits.\n *\n * Before this entry point a package author had two options, both bad: reach\n * into engine internals, or assert on whatever bytecode a parselet happened to\n * emit. The first is unstable across engine versions, the second pins the\n * implementation instead of the behaviour, so a refactor that keeps every\n * answer correct still breaks the tests. This module is a thin, dependency-free\n * layer over the same public surface a host uses: it constructs an\n * {@link ExpressionEngine} with the given packages and evaluates strings.\n *\n * It speaks in expressions. {@link expectExpression} evaluates a string and\n * asserts on the result or the failure code; {@link expectPackage} asserts on\n * the three mistakes a package actually makes (shadowing prose, colliding with\n * another package's vocabulary, and declaring an `engineVersion` range that the\n * running engine does not satisfy).\n *\n * Framework-agnostic on purpose. Nothing here imports jest, vitest or any\n * runner: an assertion that fails throws an {@link ExpectationError}, and one\n * that passes returns, so the kit drops into whatever runner the author already\n * has (or into a plain script, or `node:assert`). Runtime dependency-free and\n * side-effect free, so `solve-engine/testing` stays honest under the package's\n * `\"sideEffects\": false` contract.\n *\n * @example\n * ```ts\n * import { createTestEngine, expectExpression } from \"solve-engine/testing\";\n *\n * const engine = createTestEngine([myPackage]);\n * expectExpression(engine, \"2 gp + 3 gp\").toEqual(5, \"gp\");\n * expectExpression(engine, \"gp\").toFailWith(\"UNDEFINED_VARIABLE\");\n * ```\n */\n\nimport { ExpressionEngine } from \"@solve-js/engine/ExpressionEngine\";\nimport { BUILTIN_PACKAGES } from \"@solve-js/packages/builtins\";\nimport type { IEnginePackage } from \"@solve-js/api/PackageRegistry\";\nimport { Value, ValueType } from \"@solve-js/vm/Value\";\nimport { EngineError } from \"@solve-js/errors/EngineError\";\nimport {\n\tcheckPackageCompatibility,\n\ttype CompatibilityReport,\n\ttype CompatibilityConflict,\n\ttype CompatibilitySeverity,\n} from \"@solve-js/api/PackageCompatibility\";\nimport { checkEngineVersionCompatibility } from \"@solve-js/api/EngineVersionCompatibility\";\nimport { ENGINE_VERSION } from \"@solve-js/constants/version\";\n\n//#region Errors\n\n/**\n * The failure a matcher throws when an expectation is not met.\n *\n * A dedicated `Error` subclass rather than a bare `throw new Error`, so a\n * caller (or a reporter) can tell a kit assertion failure apart from an\n * unrelated exception with `instanceof`, and so the structured `expected` and\n * `actual` fields survive alongside the human-readable message. This is NOT an\n * {@link EngineError}: that type classifies pipeline-stage failures inside the\n * engine, whereas this classifies a test-assertion mismatch, a different\n * concern that would be miscategorised under any of `EngineError`'s categories.\n */\nexport class ExpectationError extends Error {\n\t/** A short, machine-readable label for which expectation failed. */\n\treadonly code: string;\n\t/** What the matcher was told to expect, in plain words. */\n\treadonly expected?: string;\n\t/** What it found instead. */\n\treadonly actual?: string;\n\n\tconstructor(init: { code: string; message: string; expected?: string; actual?: string }) {\n\t\tsuper(init.message);\n\t\tthis.name = \"ExpectationError\";\n\t\tthis.code = init.code;\n\t\tthis.expected = init.expected;\n\t\tthis.actual = init.actual;\n\t\t// Restore the prototype chain across the ES5 `Error` transpile target,\n\t\t// so `instanceof ExpectationError` holds for callers.\n\t\tObject.setPrototypeOf(this, ExpectationError.prototype);\n\t}\n}\n\n//#endregion\n\n//#region createTestEngine\n\n/** Options for {@link createTestEngine}. */\nexport interface TestEngineOptions {\n\t/** Locale passed to the engine. Defaults to `\"en\"`. */\n\tlocale?: string;\n\t/**\n\t * Whether to load the engine's built-in packages (arithmetic, units, dates,\n\t * and the rest) before the packages under test. Defaults to `true`, because\n\t * almost every package builds on arithmetic and most authors want a\n\t * realistic engine. Set `false` to test a package in isolation.\n\t */\n\tincludeBuiltins?: boolean;\n}\n\n/**\n * Build an {@link ExpressionEngine} loaded with the packages under test.\n *\n * The built-in packages load first (unless {@link TestEngineOptions.includeBuiltins}\n * is `false`), then each package in `packages` is registered in order, exactly\n * as a host would. Registration is honest: a package whose declared\n * `engineVersion` the running engine does not satisfy, or whose lexer keyword\n * collides with a built-in, throws here rather than being swallowed. That is\n * deliberately different from passing packages straight to the\n * `ExpressionEngine` constructor, which contains a bad package by logging and\n * continuing, useful in production, wrong for a test that needs to know the\n * package it is testing actually loaded.\n *\n * Call {@link ExpressionEngine.clear} when a test is finished with the engine\n * if the test creates many, see the engine's own lifecycle note.\n *\n * @example\n * ```ts\n * const engine = createTestEngine([myPackage]);\n * const engineOnly = createTestEngine([myPackage], { includeBuiltins: false });\n * ```\n */\nexport function createTestEngine(\n\tpackages: IEnginePackage[] = [],\n\toptions: TestEngineOptions = {},\n): ExpressionEngine {\n\tconst { locale = \"en\", includeBuiltins = true } = options;\n\n\t// Built-ins go through the constructor (their own containment applies);\n\t// the packages under test go through registerPackage() afterwards so their\n\t// failures surface as thrown errors instead of being logged and skipped.\n\tconst engine = new ExpressionEngine({ locale, packages: includeBuiltins ? BUILTIN_PACKAGES : [] });\n\tfor (const pkg of packages) {\n\t\tengine.registerPackage(pkg);\n\t}\n\treturn engine;\n}\n\n//#endregion\n\n//#region expectExpression\n\n/**\n * The normalised outcome of evaluating one expression, computed once when\n * {@link expectExpression} runs and read by every matcher on the result.\n *\n * The engine surfaces a failure two different ways, and a package author should\n * not have to know which: a parse/eval error is THROWN as an\n * {@link EngineError} (with a `.code`), while a plugin-raised error is RETURNED\n * as a {@link Value} of {@link ValueType.Error} (its `value` is the code, its\n * `unit` is the message). Both collapse to the `\"error\"` status here. A value\n * still resolving asynchronously is its own `\"pending\"` status, since the kit\n * evaluates synchronously and cannot report a final number for it.\n */\ntype Outcome =\n\t| { status: \"value\"; value: Value }\n\t| { status: \"pending\"; value: Value }\n\t| { status: \"error\"; code: string; message: string; source: EngineError | Value };\n\n/** Evaluate `expression` on `engine` and collapse both failure shapes to one outcome. */\nfunction evaluate(engine: ExpressionEngine, expression: string): Outcome {\n\ttry {\n\t\tconst value = engine.evaluateExpression(expression);\n\t\tif (value.isError()) {\n\t\t\treturn {\n\t\t\t\tstatus: \"error\",\n\t\t\t\tcode: value.errorCode ?? \"\",\n\t\t\t\tmessage: value.errorMessage ?? \"\",\n\t\t\t\tsource: value,\n\t\t\t};\n\t\t}\n\t\tif (value.isPending()) {\n\t\t\treturn { status: \"pending\", value };\n\t\t}\n\t\treturn { status: \"value\", value };\n\t} catch (error) {\n\t\tif (error instanceof EngineError) {\n\t\t\treturn { status: \"error\", code: error.code, message: error.message, source: error };\n\t\t}\n\t\t// Anything else thrown (a bug in a plugin handler, say) is still a\n\t\t// failure, wrapped so the matcher has a code and message to report.\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn {\n\t\t\tstatus: \"error\",\n\t\t\tcode: \"UNKNOWN_ERROR\",\n\t\t\tmessage,\n\t\t\tsource: new Value(ValueType.Error, \"UNKNOWN_ERROR\", message),\n\t\t};\n\t}\n}\n\n/** Whether two numbers are equal within a small tolerance scaled to their magnitude. */\nfunction numbersEqual(a: number, b: number): boolean {\n\tif (Object.is(a, b)) return true;\n\tif (!Number.isFinite(a) || !Number.isFinite(b)) return false;\n\tconst epsilon = 1e-9 * Math.max(1, Math.abs(a), Math.abs(b));\n\treturn Math.abs(a - b) <= epsilon;\n}\n\n/** A short, readable rendering of a value for an assertion message, e.g. `5 gp` or `\"abc\"`. */\nfunction describeValue(value: Value): string {\n\tif (value.type === ValueType.String) return JSON.stringify(value.value);\n\tif (value.type === ValueType.Uom && typeof value.unit === \"string\") {\n\t\treturn `${String(value.value)} ${value.unit}`;\n\t}\n\treturn String(value.value);\n}\n\n/** A short, readable rendering of an outcome for an assertion message. */\nfunction describeOutcome(outcome: Outcome): string {\n\tswitch (outcome.status) {\n\t\tcase \"value\":\n\t\t\treturn describeValue(outcome.value);\n\t\tcase \"pending\":\n\t\t\treturn \"a pending async value\";\n\t\tcase \"error\":\n\t\t\treturn `an error (${outcome.code}: ${outcome.message})`;\n\t}\n}\n\n/**\n * Assertions about the result of one evaluated expression, returned by\n * {@link expectExpression}. Every matcher returns `this`, so assertions chain,\n * and throws an {@link ExpectationError} when it fails.\n */\nexport class ExpressionAssertion {\n\tconstructor(\n\t\tprivate readonly expression: string,\n\t\tprivate readonly outcome: Outcome,\n\t) {}\n\n\t/** The raw resolved {@link Value}, for an assertion the matchers do not cover. Throws if the expression failed. */\n\tget value(): Value {\n\t\tif (this.outcome.status === \"error\") {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_VALUE\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to evaluate, but it failed with ${describeOutcome(this.outcome)}.`,\n\t\t\t\texpected: \"a resolved value\",\n\t\t\t\tactual: describeOutcome(this.outcome),\n\t\t\t});\n\t\t}\n\t\treturn this.outcome.value;\n\t}\n\n\t/**\n\t * Assert the expression evaluated to a value (not an error, not a pending\n\t * async result). Says nothing about what the value is.\n\t */\n\ttoEvaluate(): this {\n\t\tif (this.outcome.status !== \"value\") {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_EVALUATE\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to evaluate to a value, but got ${describeOutcome(this.outcome)}.`,\n\t\t\t\texpected: \"a resolved value\",\n\t\t\t\tactual: describeOutcome(this.outcome),\n\t\t\t});\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Assert the expression evaluated to `expected`, and, when `unit` is given,\n\t * that the result carries exactly that unit. A number compares against the\n\t * value's numeric magnitude within a small floating-point tolerance; a\n\t * string compares against the value's own string; a boolean against its\n\t * boolean reading. Omitting `unit` leaves the unit unchecked, so\n\t * `toEqual(5)` passes for both `5` and `5 gp`.\n\t */\n\ttoEqual(expected: number | string | boolean, unit?: string): this {\n\t\tif (this.outcome.status !== \"value\") {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_EQUAL\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to equal ${describeExpected(expected, unit)}, but got ${describeOutcome(this.outcome)}.`,\n\t\t\t\texpected: describeExpected(expected, unit),\n\t\t\t\tactual: describeOutcome(this.outcome),\n\t\t\t});\n\t\t}\n\n\t\tconst value = this.outcome.value;\n\t\tlet matches: boolean;\n\t\tif (typeof expected === \"number\") {\n\t\t\tmatches = numbersEqual(value.toNumber(), expected);\n\t\t} else if (typeof expected === \"boolean\") {\n\t\t\t// A Boolean value stores the primitive directly; anything else can\n\t\t\t// never equal a boolean, so a mismatch reports the real value.\n\t\t\tmatches = value.type === ValueType.Boolean && value.value === expected;\n\t\t} else {\n\t\t\tmatches = valueToComparableString(value) === expected;\n\t\t}\n\n\t\tif (!matches) {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_EQUAL\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to equal ${describeExpected(expected, unit)}, but it was ${describeValue(value)}.`,\n\t\t\t\texpected: describeExpected(expected, unit),\n\t\t\t\tactual: describeValue(value),\n\t\t\t});\n\t\t}\n\n\t\tif (unit !== undefined && value.unit !== unit) {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_UNIT\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to carry the unit \"${unit}\", but it was ${value.unit === undefined ? \"unitless\" : `\"${value.unit}\"`}.`,\n\t\t\t\texpected: `unit \"${unit}\"`,\n\t\t\t\tactual: value.unit === undefined ? \"no unit\" : `unit \"${value.unit}\"`,\n\t\t\t});\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/** Assert the expression failed (a thrown engine error or a plugin-raised error value). Says nothing about the code. */\n\ttoBeError(): this {\n\t\tif (this.outcome.status !== \"error\") {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_ERROR\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to fail, but it produced ${describeOutcome(this.outcome)}.`,\n\t\t\t\texpected: \"an error\",\n\t\t\t\tactual: describeOutcome(this.outcome),\n\t\t\t});\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Assert the expression failed with exactly `code`, the error catalog code\n\t * (e.g. `\"UNDEFINED_VARIABLE\"`, or a package's own code). Reports the code\n\t * it actually got when they differ, so a near-miss is obvious.\n\t */\n\ttoFailWith(code: string): this {\n\t\tif (this.outcome.status !== \"error\") {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_FAIL_WITH\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to fail with \"${code}\", but it produced ${describeOutcome(this.outcome)}.`,\n\t\t\t\texpected: `error code \"${code}\"`,\n\t\t\t\tactual: describeOutcome(this.outcome),\n\t\t\t});\n\t\t}\n\t\tif (this.outcome.code !== code) {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_FAIL_WITH\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to fail with \"${code}\", but it failed with \"${this.outcome.code}\" (${this.outcome.message}).`,\n\t\t\t\texpected: `error code \"${code}\"`,\n\t\t\t\tactual: `error code \"${this.outcome.code}\"`,\n\t\t\t});\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Assert the expression returned a value still resolving asynchronously.\n\t * The kit evaluates synchronously, so a package whose result comes from an\n\t * async resolver reports pending on first evaluation, this is how a test\n\t * confirms the async path was taken without resolving it.\n\t */\n\ttoBePending(): this {\n\t\tif (this.outcome.status !== \"pending\") {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_PENDING\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to be pending, but got ${describeOutcome(this.outcome)}.`,\n\t\t\t\texpected: \"a pending async value\",\n\t\t\t\tactual: describeOutcome(this.outcome),\n\t\t\t});\n\t\t}\n\t\treturn this;\n\t}\n}\n\n/** Render an expected value (with optional unit) for an assertion message. */\nfunction describeExpected(expected: number | string | boolean, unit?: string): string {\n\tconst base = typeof expected === \"string\" ? JSON.stringify(expected) : String(expected);\n\treturn unit === undefined ? base : `${base} ${unit}`;\n}\n\n/** The string a non-numeric value compares against in {@link ExpressionAssertion.toEqual}. */\nfunction valueToComparableString(value: Value): string {\n\t// The stored primitive stringified. For a String value this is the string\n\t// itself; for a Hex value, its `0x...` text, which is what an author writes\n\t// in a `toEqual(\"0xff\")` assertion.\n\treturn String(value.value);\n}\n\n/**\n * Evaluate `expression` on `engine` and return an assertion object.\n *\n * The expression is evaluated once, immediately, and every matcher reads that\n * one outcome, so calling several matchers on the same result does not\n * re-evaluate.\n *\n * @example\n * ```ts\n * expectExpression(engine, \"2 gp + 3 gp\").toEqual(5, \"gp\");\n * expectExpression(engine, \"gp\").toFailWith(\"UNDEFINED_VARIABLE\");\n * ```\n */\nexport function expectExpression(engine: ExpressionEngine, expression: string): ExpressionAssertion {\n\treturn new ExpressionAssertion(expression, evaluate(engine, expression));\n}\n\n//#endregion\n\n//#region expectPackage\n\n/**\n * A modest set of everyday English words a package's keywords should not claim.\n *\n * A starting point for {@link PackageAssertion.notToShadow}, not an exhaustive\n * dictionary: it leans on the function words and common nouns/verbs a package\n * is most tempted to grab as a trigger (`price`, `of`, `per`, `sum`, `total`).\n * Pass your own list to check against the specific prose your package sits in.\n */\nexport const COMMON_PROSE_WORDS: readonly string[] = [\n\t\"a\", \"an\", \"and\", \"or\", \"but\", \"if\", \"then\", \"the\", \"this\", \"that\", \"these\", \"those\",\n\t\"in\", \"on\", \"at\", \"to\", \"of\", \"for\", \"from\", \"with\", \"by\", \"as\", \"per\", \"into\", \"over\",\n\t\"is\", \"are\", \"was\", \"were\", \"be\", \"been\", \"being\", \"do\", \"does\", \"did\", \"have\", \"has\", \"had\",\n\t\"will\", \"would\", \"can\", \"could\", \"should\", \"may\", \"might\", \"must\",\n\t\"price\", \"cost\", \"value\", \"total\", \"sum\", \"count\", \"rate\", \"amount\", \"number\",\n\t\"time\", \"date\", \"day\", \"week\", \"month\", \"year\", \"hour\", \"minute\", \"second\",\n\t\"add\", \"buy\", \"sell\", \"hold\", \"make\", \"take\", \"give\", \"get\", \"set\", \"run\",\n\t\"up\", \"down\", \"out\", \"off\", \"all\", \"some\", \"any\", \"no\", \"not\", \"more\", \"less\",\n\t\"one\", \"two\", \"three\", \"first\", \"last\", \"next\", \"each\", \"every\", \"here\", \"there\",\n];\n\n/** How strict {@link PackageAssertion.notToCollideWith} is about the conflicts it will accept. */\nexport type CollisionStrictness = \"error\" | \"warning\" | \"info\";\n\n/** One shadowed word found by {@link PackageAssertion.notToShadow}: the prose word and how the package claims it. */\nexport interface ShadowedWord {\n\t/** The prose word the package claims. */\n\tword: string;\n\t/** Which descriptor field claims it. */\n\tvia: \"keyword\" | \"unit\" | \"operator\" | \"phrase\";\n\t/** The token type the word becomes, when the field maps to one. */\n\ttokenType?: string;\n}\n\n/** Severities at or above the strictness threshold, ordered most to least severe. */\nconst SEVERITY_ORDER: CompatibilitySeverity[] = [\"error\", \"warning\", \"info\"];\n\n/** Gather the single words a package claims through its declared vocabulary, which is where prose shadowing comes from. */\nfunction claimedWords(pkg: IEnginePackage): ShadowedWord[] {\n\tconst claimed: ShadowedWord[] = [];\n\tconst vocab = pkg.lexerVocabulary;\n\tif (vocab?.keywords) {\n\t\tfor (const [word, tokenType] of Object.entries(vocab.keywords)) {\n\t\t\tclaimed.push({ word, via: \"keyword\", tokenType });\n\t\t}\n\t}\n\tif (vocab?.units) {\n\t\tfor (const word of vocab.units) {\n\t\t\tclaimed.push({ word, via: \"unit\" });\n\t\t}\n\t}\n\tif (vocab?.operators) {\n\t\tfor (const [word, tokenType] of Object.entries(vocab.operators)) {\n\t\t\tclaimed.push({ word, via: \"operator\", tokenType });\n\t\t}\n\t}\n\tif (pkg.phrases) {\n\t\tfor (const [phrase, tokenType] of Object.entries(pkg.phrases)) {\n\t\t\t// A multi-word phrase is the SAFE pattern the trigger-words guide\n\t\t\t// recommends (`next friday` reserves neither word), so only a\n\t\t\t// single-word phrase can shadow a prose word.\n\t\t\tif (!phrase.includes(\" \")) {\n\t\t\t\tclaimed.push({ word: phrase, via: \"phrase\", tokenType });\n\t\t\t}\n\t\t}\n\t}\n\treturn claimed;\n}\n\n/**\n * Assertions about a package's declared descriptor, returned by\n * {@link expectPackage}. These catch the three mistakes the issue calls out,\n * before the package is ever registered. Every matcher returns `this` and\n * throws an {@link ExpectationError} when it fails.\n */\nexport class PackageAssertion {\n\tconstructor(private readonly pkg: IEnginePackage) {}\n\n\t/**\n\t * Assert none of the package's claimed words shadow a prose word.\n\t *\n\t * A trigger word that is also an ordinary word turns a line of prose into\n\t * arithmetic, the single most common package mistake and the subject of the\n\t * trigger-words guide. This checks the words the package declares\n\t * (lexer keywords, units, operators, and single-word phrases) against\n\t * `words` (defaulting to {@link COMMON_PROSE_WORDS}), case-insensitively.\n\t *\n\t * @returns the shadowed words, empty when the package is clean, for a test\n\t * that wants to inspect rather than assert.\n\t */\n\tnotToShadow(words: readonly string[] = COMMON_PROSE_WORDS): ShadowedWord[] {\n\t\tconst prose = new Set(words.map((w) => w.toLowerCase()));\n\t\tconst shadowed = claimedWords(this.pkg).filter((c) => prose.has(c.word.toLowerCase()));\n\t\tif (shadowed.length > 0) {\n\t\t\tconst list = shadowed.map((s) => `\"${s.word}\" (${s.via})`).join(\", \");\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"PACKAGE_SHADOWS_PROSE\",\n\t\t\t\tmessage: `Package \"${this.pkg.name}\" claims prose word(s) as syntax: ${list}. A word that is also ordinary English turns prose into arithmetic; prefer a multi-word phrase or a form that requires a parenthesis.`,\n\t\t\t\texpected: \"no prose words claimed as syntax\",\n\t\t\t\tactual: list,\n\t\t\t});\n\t\t}\n\t\treturn shadowed;\n\t}\n\n\t/**\n\t * Assert the package does not collide with any of `others` in a way that\n\t * would silently break one of them (two packages claiming the same lexer\n\t * keyword, plugin-function index, async-resolver namespace, and so on).\n\t *\n\t * `strictness` sets which severities fail the assertion: `\"error\"` (the\n\t * default) fails only on the collisions that always break something,\n\t * `\"warning\"` also fails on the ones that silently pick a winner, `\"info\"`\n\t * fails on cosmetic overlaps too.\n\t *\n\t * @returns the full compatibility report, so a test can inspect every\n\t * conflict, including ones below the strictness threshold.\n\t */\n\tnotToCollideWith(\n\t\tothers: IEnginePackage[],\n\t\tstrictness: CollisionStrictness = \"error\",\n\t): CompatibilityReport {\n\t\tconst report = checkPackageCompatibility(this.pkg, others);\n\t\tconst threshold = SEVERITY_ORDER.indexOf(strictness);\n\t\tconst failing = report.conflicts.filter(\n\t\t\t(c: CompatibilityConflict) => SEVERITY_ORDER.indexOf(c.severity) <= threshold,\n\t\t);\n\t\tif (failing.length > 0) {\n\t\t\tconst list = failing.map((c) => `[${c.severity}] ${c.detail}`).join(\"\\n\");\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"PACKAGE_VOCABULARY_COLLISION\",\n\t\t\t\tmessage: `Package \"${this.pkg.name}\" collides with another package:\\n${list}`,\n\t\t\t\texpected: `no conflicts at or above \"${strictness}\" severity`,\n\t\t\t\tactual: `${failing.length} conflict(s)`,\n\t\t\t});\n\t\t}\n\t\treturn report;\n\t}\n\n\t/**\n\t * Assert the package's declared `engineVersion` range is satisfied by the\n\t * running engine (or by `engineVersion` when given).\n\t *\n\t * A package that declares a range and never checks it resolves is the third\n\t * mistake the issue names: it looks fine until the one engine version it\n\t * cannot run against, where the range either fails to match or turns out to\n\t * be a malformed string. A package with no declared range passes (no\n\t * constraint is always compatible).\n\t */\n\ttoDeclareCompatibleEngineVersion(engineVersion: string = ENGINE_VERSION): this {\n\t\tconst result = checkEngineVersionCompatibility(this.pkg, engineVersion);\n\t\tif (!result.compatible) {\n\t\t\tconst detail =\n\t\t\t\tresult.reason === \"invalid-range\"\n\t\t\t\t\t? `its range \"${result.declaredRange}\" is not valid semver`\n\t\t\t\t\t: `its range \"${result.declaredRange}\" is not satisfied by engine version \"${result.engineVersion}\"`;\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"PACKAGE_ENGINE_VERSION_INCOMPATIBLE\",\n\t\t\t\tmessage: `Package \"${this.pkg.name}\" declares an engineVersion that will be rejected at registration: ${detail}.`,\n\t\t\t\texpected: `an engineVersion satisfied by \"${engineVersion}\"`,\n\t\t\t\tactual: `\"${result.declaredRange}\"`,\n\t\t\t});\n\t\t}\n\t\treturn this;\n\t}\n}\n\n/**\n * Begin an assertion about a package's declared descriptor.\n *\n * @example\n * ```ts\n * expectPackage(myPackage).notToShadow([\"price\", \"in\", \"of\"]);\n * expectPackage(myPackage).notToCollideWith(BUILTIN_PACKAGES);\n * expectPackage(myPackage).toDeclareCompatibleEngineVersion();\n * ```\n */\nexport function expectPackage(pkg: IEnginePackage): PackageAssertion {\n\treturn new PackageAssertion(pkg);\n}\n\n//#endregion\n"]}
1
+ {"version":3,"sources":["../src/testing/index.ts"],"names":["ExpectationError","_ExpectationError","init","createTestEngine","packages","options","locale","includeBuiltins","engine","ExpressionEngine","BUILTIN_PACKAGES","pkg","evaluate","expression","value","error","EngineError","message","Value","numbersEqual","a","b","epsilon","describeValue","describeOutcome","outcome","ExpressionAssertion","expected","unit","describeExpected","matches","valueToComparableString","code","base","expectExpression","COMMON_PROSE_WORDS","SEVERITY_ORDER","claimedWords","claimed","vocab","word","tokenType","phrase","PackageAssertion","words","prose","w","shadowed","c","list","s","others","strictness","report","checkPackageCompatibility","threshold","failing","engineVersion","ENGINE_VERSION","result","checkEngineVersionCompatibility","detail","expectPackage"],"mappings":"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","file":"testing.js","sourcesContent":["/**\n * A test kit for package authors, the supported way to test a package by the\n * expressions it enables rather than by the opcodes it emits.\n *\n * Before this entry point a package author had two options, both bad: reach\n * into engine internals, or assert on whatever bytecode a parselet happened to\n * emit. The first is unstable across engine versions, the second pins the\n * implementation instead of the behaviour, so a refactor that keeps every\n * answer correct still breaks the tests. This module is a thin, dependency-free\n * layer over the same public surface a host uses: it constructs an\n * {@link ExpressionEngine} with the given packages and evaluates strings.\n *\n * It speaks in expressions. {@link expectExpression} evaluates a string and\n * asserts on the result or the failure code; {@link expectPackage} asserts on\n * the three mistakes a package actually makes (shadowing prose, colliding with\n * another package's vocabulary, and declaring an `engineVersion` range that the\n * running engine does not satisfy).\n *\n * Framework-agnostic on purpose. Nothing here imports jest, vitest or any\n * runner: an assertion that fails throws an {@link ExpectationError}, and one\n * that passes returns, so the kit drops into whatever runner the author already\n * has (or into a plain script, or `node:assert`). Runtime dependency-free and\n * side-effect free, so `solve-engine/testing` stays honest under the package's\n * `\"sideEffects\": false` contract.\n *\n * @example\n * ```ts\n * import { createTestEngine, expectExpression } from \"solve-engine/testing\";\n *\n * const engine = createTestEngine([myPackage]);\n * expectExpression(engine, \"2 gp + 3 gp\").toEqual(5, \"gp\");\n * expectExpression(engine, \"gp\").toFailWith(\"UNDEFINED_VARIABLE\");\n * ```\n */\n\nimport { ExpressionEngine } from \"@solve-js/engine/ExpressionEngine\";\nimport { BUILTIN_PACKAGES } from \"@solve-js/packages/builtins\";\nimport type { IEnginePackage } from \"@solve-js/api/PackageRegistry\";\nimport { Value, ValueType } from \"@solve-js/vm/Value\";\nimport { EngineError } from \"@solve-js/errors/EngineError\";\nimport {\n\tcheckPackageCompatibility,\n\ttype CompatibilityReport,\n\ttype CompatibilityConflict,\n\ttype CompatibilitySeverity,\n} from \"@solve-js/api/PackageCompatibility\";\nimport { checkEngineVersionCompatibility } from \"@solve-js/api/EngineVersionCompatibility\";\nimport { ENGINE_VERSION } from \"@solve-js/constants/version\";\n\n//#region Errors\n\n/**\n * The failure a matcher throws when an expectation is not met.\n *\n * A dedicated `Error` subclass rather than a bare `throw new Error`, so a\n * caller (or a reporter) can tell a kit assertion failure apart from an\n * unrelated exception with `instanceof`, and so the structured `expected` and\n * `actual` fields survive alongside the human-readable message. This is NOT an\n * {@link EngineError}: that type classifies pipeline-stage failures inside the\n * engine, whereas this classifies a test-assertion mismatch, a different\n * concern that would be miscategorised under any of `EngineError`'s categories.\n */\nexport class ExpectationError extends Error {\n\t/** A short, machine-readable label for which expectation failed. */\n\treadonly code: string;\n\t/** What the matcher was told to expect, in plain words. */\n\treadonly expected?: string;\n\t/** What it found instead. */\n\treadonly actual?: string;\n\n\tconstructor(init: { code: string; message: string; expected?: string; actual?: string }) {\n\t\tsuper(init.message);\n\t\tthis.name = \"ExpectationError\";\n\t\tthis.code = init.code;\n\t\tthis.expected = init.expected;\n\t\tthis.actual = init.actual;\n\t\t// Restore the prototype chain across the ES5 `Error` transpile target,\n\t\t// so `instanceof ExpectationError` holds for callers.\n\t\tObject.setPrototypeOf(this, ExpectationError.prototype);\n\t}\n}\n\n//#endregion\n\n//#region createTestEngine\n\n/** Options for {@link createTestEngine}. */\nexport interface TestEngineOptions {\n\t/** Locale passed to the engine. Defaults to `\"en\"`. */\n\tlocale?: string;\n\t/**\n\t * Whether to load the engine's built-in packages (arithmetic, units, dates,\n\t * and the rest) before the packages under test. Defaults to `true`, because\n\t * almost every package builds on arithmetic and most authors want a\n\t * realistic engine. Set `false` to test a package in isolation.\n\t */\n\tincludeBuiltins?: boolean;\n}\n\n/**\n * Build an {@link ExpressionEngine} loaded with the packages under test.\n *\n * The built-in packages load first (unless {@link TestEngineOptions.includeBuiltins}\n * is `false`), then each package in `packages` is registered in order, exactly\n * as a host would. Registration is honest: a package whose declared\n * `engineVersion` the running engine does not satisfy, or whose lexer keyword\n * collides with a built-in, throws here rather than being swallowed. That is\n * deliberately different from passing packages straight to the\n * `ExpressionEngine` constructor, which contains a bad package by logging and\n * continuing, useful in production, wrong for a test that needs to know the\n * package it is testing actually loaded.\n *\n * Call {@link ExpressionEngine.clear} when a test is finished with the engine\n * if the test creates many, see the engine's own lifecycle note.\n *\n * @example\n * ```ts\n * const engine = createTestEngine([myPackage]);\n * const engineOnly = createTestEngine([myPackage], { includeBuiltins: false });\n * ```\n */\nexport function createTestEngine(\n\tpackages: IEnginePackage[] = [],\n\toptions: TestEngineOptions = {},\n): ExpressionEngine {\n\tconst { locale = \"en\", includeBuiltins = true } = options;\n\n\t// Built-ins go through the constructor (their own containment applies);\n\t// the packages under test go through registerPackage() afterwards so their\n\t// failures surface as thrown errors instead of being logged and skipped.\n\tconst engine = new ExpressionEngine({ locale, packages: includeBuiltins ? BUILTIN_PACKAGES : [] });\n\tfor (const pkg of packages) {\n\t\tengine.registerPackage(pkg);\n\t}\n\treturn engine;\n}\n\n//#endregion\n\n//#region expectExpression\n\n/**\n * The normalised outcome of evaluating one expression, computed once when\n * {@link expectExpression} runs and read by every matcher on the result.\n *\n * The engine surfaces a failure two different ways, and a package author should\n * not have to know which: a parse/eval error is THROWN as an\n * {@link EngineError} (with a `.code`), while a plugin-raised error is RETURNED\n * as a {@link Value} of {@link ValueType.Error} (its `value` is the code, its\n * `unit` is the message). Both collapse to the `\"error\"` status here. A value\n * still resolving asynchronously is its own `\"pending\"` status, since the kit\n * evaluates synchronously and cannot report a final number for it.\n */\ntype Outcome =\n\t| { status: \"value\"; value: Value }\n\t| { status: \"pending\"; value: Value }\n\t| { status: \"error\"; code: string; message: string; source: EngineError | Value };\n\n/** Evaluate `expression` on `engine` and collapse both failure shapes to one outcome. */\nfunction evaluate(engine: ExpressionEngine, expression: string): Outcome {\n\ttry {\n\t\tconst value = engine.evaluateExpression(expression);\n\t\tif (value.isError()) {\n\t\t\treturn {\n\t\t\t\tstatus: \"error\",\n\t\t\t\tcode: value.errorCode ?? \"\",\n\t\t\t\tmessage: value.errorMessage ?? \"\",\n\t\t\t\tsource: value,\n\t\t\t};\n\t\t}\n\t\tif (value.isPending()) {\n\t\t\treturn { status: \"pending\", value };\n\t\t}\n\t\treturn { status: \"value\", value };\n\t} catch (error) {\n\t\tif (error instanceof EngineError) {\n\t\t\treturn { status: \"error\", code: error.code, message: error.message, source: error };\n\t\t}\n\t\t// Anything else thrown (a bug in a plugin handler, say) is still a\n\t\t// failure, wrapped so the matcher has a code and message to report.\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn {\n\t\t\tstatus: \"error\",\n\t\t\tcode: \"UNKNOWN_ERROR\",\n\t\t\tmessage,\n\t\t\tsource: new Value(ValueType.Error, \"UNKNOWN_ERROR\", message),\n\t\t};\n\t}\n}\n\n/** Whether two numbers are equal within a small tolerance scaled to their magnitude. */\nfunction numbersEqual(a: number, b: number): boolean {\n\tif (Object.is(a, b)) return true;\n\tif (!Number.isFinite(a) || !Number.isFinite(b)) return false;\n\tconst epsilon = 1e-9 * Math.max(1, Math.abs(a), Math.abs(b));\n\treturn Math.abs(a - b) <= epsilon;\n}\n\n/** A short, readable rendering of a value for an assertion message, e.g. `5 gp` or `\"abc\"`. */\nfunction describeValue(value: Value): string {\n\tif (value.type === ValueType.String) return JSON.stringify(value.value);\n\tif (value.type === ValueType.Uom && typeof value.unit === \"string\") {\n\t\treturn `${String(value.value)} ${value.unit}`;\n\t}\n\treturn String(value.value);\n}\n\n/** A short, readable rendering of an outcome for an assertion message. */\nfunction describeOutcome(outcome: Outcome): string {\n\tswitch (outcome.status) {\n\t\tcase \"value\":\n\t\t\treturn describeValue(outcome.value);\n\t\tcase \"pending\":\n\t\t\treturn \"a pending async value\";\n\t\tcase \"error\":\n\t\t\treturn `an error (${outcome.code}: ${outcome.message})`;\n\t}\n}\n\n/**\n * Assertions about the result of one evaluated expression, returned by\n * {@link expectExpression}. Every matcher returns `this`, so assertions chain,\n * and throws an {@link ExpectationError} when it fails.\n */\nexport class ExpressionAssertion {\n\tconstructor(\n\t\tprivate readonly expression: string,\n\t\tprivate readonly outcome: Outcome,\n\t) {}\n\n\t/** The raw resolved {@link Value}, for an assertion the matchers do not cover. Throws if the expression failed. */\n\tget value(): Value {\n\t\tif (this.outcome.status === \"error\") {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_VALUE\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to evaluate, but it failed with ${describeOutcome(this.outcome)}.`,\n\t\t\t\texpected: \"a resolved value\",\n\t\t\t\tactual: describeOutcome(this.outcome),\n\t\t\t});\n\t\t}\n\t\treturn this.outcome.value;\n\t}\n\n\t/**\n\t * Assert the expression evaluated to a value (not an error, not a pending\n\t * async result). Says nothing about what the value is.\n\t */\n\ttoEvaluate(): this {\n\t\tif (this.outcome.status !== \"value\") {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_EVALUATE\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to evaluate to a value, but got ${describeOutcome(this.outcome)}.`,\n\t\t\t\texpected: \"a resolved value\",\n\t\t\t\tactual: describeOutcome(this.outcome),\n\t\t\t});\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Assert the expression evaluated to `expected`, and, when `unit` is given,\n\t * that the result carries exactly that unit. A number compares against the\n\t * value's numeric magnitude within a small floating-point tolerance; a\n\t * string compares against the value's own string; a boolean against its\n\t * boolean reading. Omitting `unit` leaves the unit unchecked, so\n\t * `toEqual(5)` passes for both `5` and `5 gp`.\n\t */\n\ttoEqual(expected: number | string | boolean, unit?: string): this {\n\t\tif (this.outcome.status !== \"value\") {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_EQUAL\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to equal ${describeExpected(expected, unit)}, but got ${describeOutcome(this.outcome)}.`,\n\t\t\t\texpected: describeExpected(expected, unit),\n\t\t\t\tactual: describeOutcome(this.outcome),\n\t\t\t});\n\t\t}\n\n\t\tconst value = this.outcome.value;\n\t\tlet matches: boolean;\n\t\tif (typeof expected === \"number\") {\n\t\t\tmatches = numbersEqual(value.toNumber(), expected);\n\t\t} else if (typeof expected === \"boolean\") {\n\t\t\t// A Boolean value stores the primitive directly; anything else can\n\t\t\t// never equal a boolean, so a mismatch reports the real value.\n\t\t\tmatches = value.type === ValueType.Boolean && value.value === expected;\n\t\t} else {\n\t\t\tmatches = valueToComparableString(value) === expected;\n\t\t}\n\n\t\tif (!matches) {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_EQUAL\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to equal ${describeExpected(expected, unit)}, but it was ${describeValue(value)}.`,\n\t\t\t\texpected: describeExpected(expected, unit),\n\t\t\t\tactual: describeValue(value),\n\t\t\t});\n\t\t}\n\n\t\tif (unit !== undefined && value.unit !== unit) {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_UNIT\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to carry the unit \"${unit}\", but it was ${value.unit === undefined ? \"unitless\" : `\"${value.unit}\"`}.`,\n\t\t\t\texpected: `unit \"${unit}\"`,\n\t\t\t\tactual: value.unit === undefined ? \"no unit\" : `unit \"${value.unit}\"`,\n\t\t\t});\n\t\t}\n\n\t\treturn this;\n\t}\n\n\t/** Assert the expression failed (a thrown engine error or a plugin-raised error value). Says nothing about the code. */\n\ttoBeError(): this {\n\t\tif (this.outcome.status !== \"error\") {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_ERROR\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to fail, but it produced ${describeOutcome(this.outcome)}.`,\n\t\t\t\texpected: \"an error\",\n\t\t\t\tactual: describeOutcome(this.outcome),\n\t\t\t});\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Assert the expression failed with exactly `code`, the error catalog code\n\t * (e.g. `\"UNDEFINED_VARIABLE\"`, or a package's own code). Reports the code\n\t * it actually got when they differ, so a near-miss is obvious.\n\t */\n\ttoFailWith(code: string): this {\n\t\tif (this.outcome.status !== \"error\") {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_FAIL_WITH\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to fail with \"${code}\", but it produced ${describeOutcome(this.outcome)}.`,\n\t\t\t\texpected: `error code \"${code}\"`,\n\t\t\t\tactual: describeOutcome(this.outcome),\n\t\t\t});\n\t\t}\n\t\tif (this.outcome.code !== code) {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_FAIL_WITH\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to fail with \"${code}\", but it failed with \"${this.outcome.code}\" (${this.outcome.message}).`,\n\t\t\t\texpected: `error code \"${code}\"`,\n\t\t\t\tactual: `error code \"${this.outcome.code}\"`,\n\t\t\t});\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * Assert the expression returned a value still resolving asynchronously.\n\t * The kit evaluates synchronously, so a package whose result comes from an\n\t * async resolver reports pending on first evaluation, this is how a test\n\t * confirms the async path was taken without resolving it.\n\t */\n\ttoBePending(): this {\n\t\tif (this.outcome.status !== \"pending\") {\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"EXPECTED_PENDING\",\n\t\t\t\tmessage: `Expected \"${this.expression}\" to be pending, but got ${describeOutcome(this.outcome)}.`,\n\t\t\t\texpected: \"a pending async value\",\n\t\t\t\tactual: describeOutcome(this.outcome),\n\t\t\t});\n\t\t}\n\t\treturn this;\n\t}\n}\n\n/** Render an expected value (with optional unit) for an assertion message. */\nfunction describeExpected(expected: number | string | boolean, unit?: string): string {\n\tconst base = typeof expected === \"string\" ? JSON.stringify(expected) : String(expected);\n\treturn unit === undefined ? base : `${base} ${unit}`;\n}\n\n/** The string a non-numeric value compares against in {@link ExpressionAssertion.toEqual}. */\nfunction valueToComparableString(value: Value): string {\n\t// The stored primitive stringified. For a String value this is the string\n\t// itself; for a Hex value, its `0x...` text, which is what an author writes\n\t// in a `toEqual(\"0xff\")` assertion.\n\treturn String(value.value);\n}\n\n/**\n * Evaluate `expression` on `engine` and return an assertion object.\n *\n * The expression is evaluated once, immediately, and every matcher reads that\n * one outcome, so calling several matchers on the same result does not\n * re-evaluate.\n *\n * @example\n * ```ts\n * expectExpression(engine, \"2 gp + 3 gp\").toEqual(5, \"gp\");\n * expectExpression(engine, \"gp\").toFailWith(\"UNDEFINED_VARIABLE\");\n * ```\n */\nexport function expectExpression(engine: ExpressionEngine, expression: string): ExpressionAssertion {\n\treturn new ExpressionAssertion(expression, evaluate(engine, expression));\n}\n\n//#endregion\n\n//#region expectPackage\n\n/**\n * A modest set of everyday English words a package's keywords should not claim.\n *\n * A starting point for {@link PackageAssertion.notToShadow}, not an exhaustive\n * dictionary: it leans on the function words and common nouns/verbs a package\n * is most tempted to grab as a trigger (`price`, `of`, `per`, `sum`, `total`).\n * Pass your own list to check against the specific prose your package sits in.\n */\nexport const COMMON_PROSE_WORDS: readonly string[] = [\n\t\"a\", \"an\", \"and\", \"or\", \"but\", \"if\", \"then\", \"the\", \"this\", \"that\", \"these\", \"those\",\n\t\"in\", \"on\", \"at\", \"to\", \"of\", \"for\", \"from\", \"with\", \"by\", \"as\", \"per\", \"into\", \"over\",\n\t\"is\", \"are\", \"was\", \"were\", \"be\", \"been\", \"being\", \"do\", \"does\", \"did\", \"have\", \"has\", \"had\",\n\t\"will\", \"would\", \"can\", \"could\", \"should\", \"may\", \"might\", \"must\",\n\t\"price\", \"cost\", \"value\", \"total\", \"sum\", \"count\", \"rate\", \"amount\", \"number\",\n\t\"time\", \"date\", \"day\", \"week\", \"month\", \"year\", \"hour\", \"minute\", \"second\",\n\t\"add\", \"buy\", \"sell\", \"hold\", \"make\", \"take\", \"give\", \"get\", \"set\", \"run\",\n\t\"up\", \"down\", \"out\", \"off\", \"all\", \"some\", \"any\", \"no\", \"not\", \"more\", \"less\",\n\t\"one\", \"two\", \"three\", \"first\", \"last\", \"next\", \"each\", \"every\", \"here\", \"there\",\n];\n\n/** How strict {@link PackageAssertion.notToCollideWith} is about the conflicts it will accept. */\nexport type CollisionStrictness = \"error\" | \"warning\" | \"info\";\n\n/** One shadowed word found by {@link PackageAssertion.notToShadow}: the prose word and how the package claims it. */\nexport interface ShadowedWord {\n\t/** The prose word the package claims. */\n\tword: string;\n\t/** Which descriptor field claims it. */\n\tvia: \"keyword\" | \"unit\" | \"operator\" | \"phrase\";\n\t/** The token type the word becomes, when the field maps to one. */\n\ttokenType?: string;\n}\n\n/** Severities at or above the strictness threshold, ordered most to least severe. */\nconst SEVERITY_ORDER: CompatibilitySeverity[] = [\"error\", \"warning\", \"info\"];\n\n/** Gather the single words a package claims through its declared vocabulary, which is where prose shadowing comes from. */\nfunction claimedWords(pkg: IEnginePackage): ShadowedWord[] {\n\tconst claimed: ShadowedWord[] = [];\n\tconst vocab = pkg.lexerVocabulary;\n\tif (vocab?.keywords) {\n\t\tfor (const [word, tokenType] of Object.entries(vocab.keywords)) {\n\t\t\tclaimed.push({ word, via: \"keyword\", tokenType });\n\t\t}\n\t}\n\tif (vocab?.units) {\n\t\tfor (const word of vocab.units) {\n\t\t\tclaimed.push({ word, via: \"unit\" });\n\t\t}\n\t}\n\tif (vocab?.operators) {\n\t\tfor (const [word, tokenType] of Object.entries(vocab.operators)) {\n\t\t\tclaimed.push({ word, via: \"operator\", tokenType });\n\t\t}\n\t}\n\tif (pkg.phrases) {\n\t\tfor (const [phrase, tokenType] of Object.entries(pkg.phrases)) {\n\t\t\t// A multi-word phrase is the SAFE pattern the trigger-words guide\n\t\t\t// recommends (`next friday` reserves neither word), so only a\n\t\t\t// single-word phrase can shadow a prose word.\n\t\t\tif (!phrase.includes(\" \")) {\n\t\t\t\tclaimed.push({ word: phrase, via: \"phrase\", tokenType });\n\t\t\t}\n\t\t}\n\t}\n\treturn claimed;\n}\n\n/**\n * Assertions about a package's declared descriptor, returned by\n * {@link expectPackage}. These catch the three mistakes the issue calls out,\n * before the package is ever registered. Every matcher returns `this` and\n * throws an {@link ExpectationError} when it fails.\n */\nexport class PackageAssertion {\n\tconstructor(private readonly pkg: IEnginePackage) {}\n\n\t/**\n\t * Assert none of the package's claimed words shadow a prose word.\n\t *\n\t * A trigger word that is also an ordinary word turns a line of prose into\n\t * arithmetic, the single most common package mistake and the subject of the\n\t * trigger-words guide. This checks the words the package declares\n\t * (lexer keywords, units, operators, and single-word phrases) against\n\t * `words` (defaulting to {@link COMMON_PROSE_WORDS}), case-insensitively.\n\t *\n\t * @returns the shadowed words, empty when the package is clean, for a test\n\t * that wants to inspect rather than assert.\n\t */\n\tnotToShadow(words: readonly string[] = COMMON_PROSE_WORDS): ShadowedWord[] {\n\t\tconst prose = new Set(words.map((w) => w.toLowerCase()));\n\t\tconst shadowed = claimedWords(this.pkg).filter((c) => prose.has(c.word.toLowerCase()));\n\t\tif (shadowed.length > 0) {\n\t\t\tconst list = shadowed.map((s) => `\"${s.word}\" (${s.via})`).join(\", \");\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"PACKAGE_SHADOWS_PROSE\",\n\t\t\t\tmessage: `Package \"${this.pkg.name}\" claims prose word(s) as syntax: ${list}. A word that is also ordinary English turns prose into arithmetic; prefer a multi-word phrase or a form that requires a parenthesis.`,\n\t\t\t\texpected: \"no prose words claimed as syntax\",\n\t\t\t\tactual: list,\n\t\t\t});\n\t\t}\n\t\treturn shadowed;\n\t}\n\n\t/**\n\t * Assert the package does not collide with any of `others` in a way that\n\t * would silently break one of them (two packages claiming the same lexer\n\t * keyword, plugin-function index, async-resolver namespace, and so on).\n\t *\n\t * `strictness` sets which severities fail the assertion: `\"error\"` (the\n\t * default) fails only on the collisions that always break something,\n\t * `\"warning\"` also fails on the ones that silently pick a winner, `\"info\"`\n\t * fails on cosmetic overlaps too.\n\t *\n\t * @returns the full compatibility report, so a test can inspect every\n\t * conflict, including ones below the strictness threshold.\n\t */\n\tnotToCollideWith(\n\t\tothers: IEnginePackage[],\n\t\tstrictness: CollisionStrictness = \"error\",\n\t): CompatibilityReport {\n\t\tconst report = checkPackageCompatibility(this.pkg, others);\n\t\tconst threshold = SEVERITY_ORDER.indexOf(strictness);\n\t\tconst failing = report.conflicts.filter(\n\t\t\t(c: CompatibilityConflict) => SEVERITY_ORDER.indexOf(c.severity) <= threshold,\n\t\t);\n\t\tif (failing.length > 0) {\n\t\t\tconst list = failing.map((c) => `[${c.severity}] ${c.detail}`).join(\"\\n\");\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"PACKAGE_VOCABULARY_COLLISION\",\n\t\t\t\tmessage: `Package \"${this.pkg.name}\" collides with another package:\\n${list}`,\n\t\t\t\texpected: `no conflicts at or above \"${strictness}\" severity`,\n\t\t\t\tactual: `${failing.length} conflict(s)`,\n\t\t\t});\n\t\t}\n\t\treturn report;\n\t}\n\n\t/**\n\t * Assert the package's declared `engineVersion` range is satisfied by the\n\t * running engine (or by `engineVersion` when given).\n\t *\n\t * A package that declares a range and never checks it resolves is the third\n\t * mistake the issue names: it looks fine until the one engine version it\n\t * cannot run against, where the range either fails to match or turns out to\n\t * be a malformed string. A package with no declared range passes (no\n\t * constraint is always compatible).\n\t */\n\ttoDeclareCompatibleEngineVersion(engineVersion: string = ENGINE_VERSION): this {\n\t\tconst result = checkEngineVersionCompatibility(this.pkg, engineVersion);\n\t\tif (!result.compatible) {\n\t\t\tconst detail =\n\t\t\t\tresult.reason === \"invalid-range\"\n\t\t\t\t\t? `its range \"${result.declaredRange}\" is not valid semver`\n\t\t\t\t\t: `its range \"${result.declaredRange}\" is not satisfied by engine version \"${result.engineVersion}\"`;\n\t\t\tthrow new ExpectationError({\n\t\t\t\tcode: \"PACKAGE_ENGINE_VERSION_INCOMPATIBLE\",\n\t\t\t\tmessage: `Package \"${this.pkg.name}\" declares an engineVersion that will be rejected at registration: ${detail}.`,\n\t\t\t\texpected: `an engineVersion satisfied by \"${engineVersion}\"`,\n\t\t\t\tactual: `\"${result.declaredRange}\"`,\n\t\t\t});\n\t\t}\n\t\treturn this;\n\t}\n}\n\n/**\n * Begin an assertion about a package's declared descriptor.\n *\n * @example\n * ```ts\n * expectPackage(myPackage).notToShadow([\"price\", \"in\", \"of\"]);\n * expectPackage(myPackage).notToCollideWith(BUILTIN_PACKAGES);\n * expectPackage(myPackage).toDeclareCompatibleEngineVersion();\n * ```\n */\nexport function expectPackage(pkg: IEnginePackage): PackageAssertion {\n\treturn new PackageAssertion(pkg);\n}\n\n//#endregion\n"]}
package/dist/uom.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var chunkA755LVPT_cjs=require('./chunk-A755LVPT.cjs'),chunkDUFEONVN_cjs=require('./chunk-DUFEONVN.cjs');require('./chunk-ABVDKMNF.cjs'),require('./chunk-TLG7VZRX.cjs'),require('./chunk-OM7NOHJF.cjs');var chunkPHWIO4P3_cjs=require('./chunk-PHWIO4P3.cjs');require('./chunk-EZKR44MA.cjs'),require('./chunk-SUAGBRQ7.cjs');Object.defineProperty(exports,"CurrencyAsyncResolver",{enumerable:true,get:function(){return chunkA755LVPT_cjs.b}});Object.defineProperty(exports,"CurrencyExchangeService",{enumerable:true,get:function(){return chunkDUFEONVN_cjs.a}});Object.defineProperty(exports,"currencyExchangeService",{enumerable:true,get:function(){return chunkDUFEONVN_cjs.b}});Object.defineProperty(exports,"sharedCurrencyExchange",{enumerable:true,get:function(){return chunkDUFEONVN_cjs.c}});Object.defineProperty(exports,"canConvert",{enumerable:true,get:function(){return chunkPHWIO4P3_cjs.d}});Object.defineProperty(exports,"convertUnit",{enumerable:true,get:function(){return chunkPHWIO4P3_cjs.e}});Object.defineProperty(exports,"getBestUnit",{enumerable:true,get:function(){return chunkPHWIO4P3_cjs.h}});Object.defineProperty(exports,"getMeasure",{enumerable:true,get:function(){return chunkPHWIO4P3_cjs.c}});Object.defineProperty(exports,"isConvertibleUnit",{enumerable:true,get:function(){return chunkPHWIO4P3_cjs.g}});Object.defineProperty(exports,"resolveUnit",{enumerable:true,get:function(){return chunkPHWIO4P3_cjs.b}});//# sourceMappingURL=uom.cjs.map
1
+ 'use strict';var chunkZSXQP7PD_cjs=require('./chunk-ZSXQP7PD.cjs');require('./chunk-GDLYXRMA.cjs');var chunkSF5QVUEI_cjs=require('./chunk-SF5QVUEI.cjs');require('./chunk-ABVDKMNF.cjs'),require('./chunk-TLG7VZRX.cjs'),require('./chunk-S3SPDK6N.cjs');var chunkPHWIO4P3_cjs=require('./chunk-PHWIO4P3.cjs');require('./chunk-EZKR44MA.cjs'),require('./chunk-6SYU4MH7.cjs');Object.defineProperty(exports,"CurrencyAsyncResolver",{enumerable:true,get:function(){return chunkZSXQP7PD_cjs.a}});Object.defineProperty(exports,"CurrencyExchangeService",{enumerable:true,get:function(){return chunkSF5QVUEI_cjs.a}});Object.defineProperty(exports,"currencyExchangeService",{enumerable:true,get:function(){return chunkSF5QVUEI_cjs.b}});Object.defineProperty(exports,"sharedCurrencyExchange",{enumerable:true,get:function(){return chunkSF5QVUEI_cjs.c}});Object.defineProperty(exports,"canConvert",{enumerable:true,get:function(){return chunkPHWIO4P3_cjs.d}});Object.defineProperty(exports,"convertUnit",{enumerable:true,get:function(){return chunkPHWIO4P3_cjs.e}});Object.defineProperty(exports,"getBestUnit",{enumerable:true,get:function(){return chunkPHWIO4P3_cjs.h}});Object.defineProperty(exports,"getMeasure",{enumerable:true,get:function(){return chunkPHWIO4P3_cjs.c}});Object.defineProperty(exports,"isConvertibleUnit",{enumerable:true,get:function(){return chunkPHWIO4P3_cjs.g}});Object.defineProperty(exports,"resolveUnit",{enumerable:true,get:function(){return chunkPHWIO4P3_cjs.b}});//# sourceMappingURL=uom.cjs.map
2
2
  //# sourceMappingURL=uom.cjs.map
package/dist/uom.d.cts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { QueryClient } from '@tanstack/query-core';
2
2
  import { T as Token } from './Token-D8f7yaz1.cjs';
3
- import { a as BytecodeProgram } from './BytecodeBuilder-DSWKZi4f.cjs';
3
+ import { O as OpCode, a as BytecodeProgram } from './BytecodeBuilder-DSWKZi4f.cjs';
4
4
  import { IAsyncResolver, AsyncCheckResult } from './resolvers.cjs';
5
- import './Value-BYHw-x7q.cjs';
5
+ import './Value-2TIKi-YL.cjs';
6
6
 
7
7
  /**
8
8
  * Caches exchange rates fetched from an external source.
@@ -40,6 +40,27 @@ declare class CurrencyExchangeService {
40
40
  */
41
41
  private static readonly CRYPTO_IDS;
42
42
  private isCryptoCode;
43
+ /**
44
+ * Remembered {@link isCurrency} answers, keyed by the spelling asked about.
45
+ *
46
+ * The VM asks this question on every unit-bearing instruction (a `UOM_CONVERT`
47
+ * for `5 kg`, a `MUL` of money by a count, a `DIV` of two quantities), and each
48
+ * ask used to upper-case the code twice and probe two tables. The answer never
49
+ * changes for a given spelling: the ISO 4217 set and {@link CRYPTO_IDS} are
50
+ * both fixed for the life of the process, so remembering it is safe and the
51
+ * ask becomes one map read. Keyed by the raw spelling rather than its
52
+ * upper-cased form so the hot path allocates nothing.
53
+ */
54
+ private readonly currencyAnswers;
55
+ /**
56
+ * How many spellings the cache will hold before it is emptied.
57
+ *
58
+ * A document's unit vocabulary is small and closed, so an ordinary run never
59
+ * comes near this. The bound exists for the public `./vm` surface, where a
60
+ * host can hand `UOM_CONVERT` any string it likes; emptying rather than
61
+ * evicting keeps the miss path free of bookkeeping.
62
+ */
63
+ private static readonly MAX_REMEMBERED_CODES;
43
64
  constructor();
44
65
  /**
45
66
  * Timeout (ms) for currency exchange rate fetches.
@@ -130,6 +151,10 @@ declare class CurrencyExchangeService {
130
151
  * Recognising a code is not the same as having a rate for it. That is
131
152
  * answered later, by the exchange provider; conflating the two is what
132
153
  * produced the silent failure.
154
+ *
155
+ * Remembered per spelling (see {@link currencyAnswers}), because the VM asks
156
+ * on every unit-bearing instruction and the answer for a spelling never
157
+ * changes.
133
158
  */
134
159
  isCurrency(code: string): boolean;
135
160
  }
@@ -153,6 +178,14 @@ declare const sharedCurrencyExchange: CurrencyExchangeService;
153
178
  */
154
179
  declare class CurrencyAsyncResolver implements IAsyncResolver {
155
180
  readonly namespace = "currency";
181
+ /**
182
+ * Every unit the scan below reads arrives as a `PUSH_STRING` operand, so a
183
+ * program with no string constant cannot name a currency and the engine
184
+ * need not ask. Deliberately not the arithmetic opcodes the scan also
185
+ * checks: `ADD` is in nearly every line, and declaring it would spare
186
+ * nothing. See {@link IAsyncResolver.watchedOpcodes}.
187
+ */
188
+ readonly watchedOpcodes: readonly OpCode[];
156
189
  private exchange;
157
190
  constructor(exchange?: CurrencyExchangeService);
158
191
  preflight(_tokens: Token[], bytecode: BytecodeProgram, packageId: string, signal: AbortSignal, queryClient: QueryClient): AsyncCheckResult | null;
package/dist/uom.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { QueryClient } from '@tanstack/query-core';
2
2
  import { T as Token } from './Token-D8f7yaz1.js';
3
- import { a as BytecodeProgram } from './BytecodeBuilder-DSWKZi4f.js';
3
+ import { O as OpCode, a as BytecodeProgram } from './BytecodeBuilder-DSWKZi4f.js';
4
4
  import { IAsyncResolver, AsyncCheckResult } from './resolvers.js';
5
- import './Value-BYHw-x7q.js';
5
+ import './Value-2TIKi-YL.js';
6
6
 
7
7
  /**
8
8
  * Caches exchange rates fetched from an external source.
@@ -40,6 +40,27 @@ declare class CurrencyExchangeService {
40
40
  */
41
41
  private static readonly CRYPTO_IDS;
42
42
  private isCryptoCode;
43
+ /**
44
+ * Remembered {@link isCurrency} answers, keyed by the spelling asked about.
45
+ *
46
+ * The VM asks this question on every unit-bearing instruction (a `UOM_CONVERT`
47
+ * for `5 kg`, a `MUL` of money by a count, a `DIV` of two quantities), and each
48
+ * ask used to upper-case the code twice and probe two tables. The answer never
49
+ * changes for a given spelling: the ISO 4217 set and {@link CRYPTO_IDS} are
50
+ * both fixed for the life of the process, so remembering it is safe and the
51
+ * ask becomes one map read. Keyed by the raw spelling rather than its
52
+ * upper-cased form so the hot path allocates nothing.
53
+ */
54
+ private readonly currencyAnswers;
55
+ /**
56
+ * How many spellings the cache will hold before it is emptied.
57
+ *
58
+ * A document's unit vocabulary is small and closed, so an ordinary run never
59
+ * comes near this. The bound exists for the public `./vm` surface, where a
60
+ * host can hand `UOM_CONVERT` any string it likes; emptying rather than
61
+ * evicting keeps the miss path free of bookkeeping.
62
+ */
63
+ private static readonly MAX_REMEMBERED_CODES;
43
64
  constructor();
44
65
  /**
45
66
  * Timeout (ms) for currency exchange rate fetches.
@@ -130,6 +151,10 @@ declare class CurrencyExchangeService {
130
151
  * Recognising a code is not the same as having a rate for it. That is
131
152
  * answered later, by the exchange provider; conflating the two is what
132
153
  * produced the silent failure.
154
+ *
155
+ * Remembered per spelling (see {@link currencyAnswers}), because the VM asks
156
+ * on every unit-bearing instruction and the answer for a spelling never
157
+ * changes.
133
158
  */
134
159
  isCurrency(code: string): boolean;
135
160
  }
@@ -153,6 +178,14 @@ declare const sharedCurrencyExchange: CurrencyExchangeService;
153
178
  */
154
179
  declare class CurrencyAsyncResolver implements IAsyncResolver {
155
180
  readonly namespace = "currency";
181
+ /**
182
+ * Every unit the scan below reads arrives as a `PUSH_STRING` operand, so a
183
+ * program with no string constant cannot name a currency and the engine
184
+ * need not ask. Deliberately not the arithmetic opcodes the scan also
185
+ * checks: `ADD` is in nearly every line, and declaring it would spare
186
+ * nothing. See {@link IAsyncResolver.watchedOpcodes}.
187
+ */
188
+ readonly watchedOpcodes: readonly OpCode[];
156
189
  private exchange;
157
190
  constructor(exchange?: CurrencyExchangeService);
158
191
  preflight(_tokens: Token[], bytecode: BytecodeProgram, packageId: string, signal: AbortSignal, queryClient: QueryClient): AsyncCheckResult | null;
package/dist/uom.js CHANGED
@@ -1,2 +1,2 @@
1
- export{b as CurrencyAsyncResolver}from'./chunk-SFM4XFGJ.js';export{a as CurrencyExchangeService,b as currencyExchangeService,c as sharedCurrencyExchange}from'./chunk-PTXUWGRR.js';import'./chunk-TZYMXNIB.js';import'./chunk-HFKDWQUL.js';import'./chunk-X5K72MBV.js';export{d as canConvert,e as convertUnit,h as getBestUnit,c as getMeasure,g as isConvertibleUnit,b as resolveUnit}from'./chunk-BWTVJD5L.js';import'./chunk-PRSXXDTA.js';import'./chunk-RELMEWY6.js';//# sourceMappingURL=uom.js.map
1
+ export{a as CurrencyAsyncResolver}from'./chunk-G5TZ6TDA.js';import'./chunk-EOKHRS2T.js';export{a as CurrencyExchangeService,b as currencyExchangeService,c as sharedCurrencyExchange}from'./chunk-PICFFFJV.js';import'./chunk-TZYMXNIB.js';import'./chunk-HFKDWQUL.js';import'./chunk-O7HF345B.js';export{d as canConvert,e as convertUnit,h as getBestUnit,c as getMeasure,g as isConvertibleUnit,b as resolveUnit}from'./chunk-BWTVJD5L.js';import'./chunk-PRSXXDTA.js';import'./chunk-6G2NES2I.js';//# sourceMappingURL=uom.js.map
2
2
  //# sourceMappingURL=uom.js.map
package/dist/vm.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var chunkUNKZ5XRC_cjs=require('./chunk-UNKZ5XRC.cjs');require('./chunk-HG4NPDN5.cjs');var chunkLCYQQFUH_cjs=require('./chunk-LCYQQFUH.cjs');require('./chunk-CM2WM5CM.cjs'),require('./chunk-DUFEONVN.cjs'),require('./chunk-ABVDKMNF.cjs'),require('./chunk-TLG7VZRX.cjs'),require('./chunk-YWF6C2IO.cjs'),require('./chunk-A764BY7L.cjs'),require('./chunk-E4HAKNBQ.cjs');var chunkOM7NOHJF_cjs=require('./chunk-OM7NOHJF.cjs');require('./chunk-PHWIO4P3.cjs'),require('./chunk-EZKR44MA.cjs'),require('./chunk-SUAGBRQ7.cjs');var l=class{constructor(t){this.checkpoints=[];this.vm=t;}snapshot(t,n,e){if(e.length===0)return null;let r=this.checkpoints.length>0?this.checkpoints[this.checkpoints.length-1]:null,o=Object.create(r?.variables??null),i=Object.create(r?.functions??null);for(let s of e){if(this.vm.hasUserFunction(s)){let p=this.vm.getUserFunction(s);p&&(i[s]=p);continue}let u=this.vm.getVar(s);u!==void 0&&(o[s]=u);}let c={lineNumber:t,lineId:n,variables:o,functions:i,parent:r};return this.checkpoints.push(c),c}restoreTo(t){let n=this.getNearestCheckpoint(t);if(!n){this.vm.reset();return}let e=[],r=n;for(;r;)e.unshift(r),r=r.parent;this.vm.reset();for(let o of e){for(let i of Object.keys(o.variables))this.vm.setVar(i,o.variables[i]);for(let i of Object.keys(o.functions)){let c=o.functions[i];this.vm.defineUserFunction(c.name,c.params,c.program);}}}getNearestCheckpoint(t){let n=null;for(let e of this.checkpoints)if(e.lineNumber<=t)n=e;else break;return n}getCheckpointAt(t){return this.checkpoints.find(n=>n.lineNumber===t)}getAllCheckpoints(){return this.checkpoints}lookupVariable(t){if(this.checkpoints.length===0)return;let e=this.checkpoints[this.checkpoints.length-1].variables;for(;e;){if(Object.prototype.hasOwnProperty.call(e,t))return e[t];e=Object.getPrototypeOf(e);}}clear(){this.checkpoints=[];}get count(){return this.checkpoints.length}get isEmpty(){return this.checkpoints.length===0}get vmInstance(){return this.vm}};Object.defineProperty(exports,"DependencyGraph",{enumerable:true,get:function(){return chunkUNKZ5XRC_cjs.a}});Object.defineProperty(exports,"ScopeManager",{enumerable:true,get:function(){return chunkUNKZ5XRC_cjs.b}});Object.defineProperty(exports,"createVM",{enumerable:true,get:function(){return chunkUNKZ5XRC_cjs.c}});Object.defineProperty(exports,"executeBytecode",{enumerable:true,get:function(){return chunkUNKZ5XRC_cjs.d}});Object.defineProperty(exports,"OpRegistry",{enumerable:true,get:function(){return chunkLCYQQFUH_cjs.v}});Object.defineProperty(exports,"allocatePluginFunctionIndex",{enumerable:true,get:function(){return chunkLCYQQFUH_cjs.E}});Object.defineProperty(exports,"binaryOp",{enumerable:true,get:function(){return chunkLCYQQFUH_cjs.u}});Object.defineProperty(exports,"builtinFunctions",{enumerable:true,get:function(){return chunkLCYQQFUH_cjs.C}});Object.defineProperty(exports,"pluginFunctionIndexFor",{enumerable:true,get:function(){return chunkLCYQQFUH_cjs.F}});Object.defineProperty(exports,"pluginFunctionRegistry",{enumerable:true,get:function(){return chunkLCYQQFUH_cjs.D}});Object.defineProperty(exports,"sharedOpRegistry",{enumerable:true,get:function(){return chunkLCYQQFUH_cjs.w}});Object.defineProperty(exports,"unifyUom",{enumerable:true,get:function(){return chunkLCYQQFUH_cjs.j}});Object.defineProperty(exports,"Value",{enumerable:true,get:function(){return chunkOM7NOHJF_cjs.m}});Object.defineProperty(exports,"ValueType",{enumerable:true,get:function(){return chunkOM7NOHJF_cjs.g}});Object.defineProperty(exports,"bigIntValue",{enumerable:true,get:function(){return chunkOM7NOHJF_cjs.s}});Object.defineProperty(exports,"chargeAllocation",{enumerable:true,get:function(){return chunkOM7NOHJF_cjs.c}});Object.defineProperty(exports,"checkAllocation",{enumerable:true,get:function(){return chunkOM7NOHJF_cjs.d}});Object.defineProperty(exports,"checkedArray",{enumerable:true,get:function(){return chunkOM7NOHJF_cjs.e}});Object.defineProperty(exports,"colVectorValue",{enumerable:true,get:function(){return chunkOM7NOHJF_cjs.E}});Object.defineProperty(exports,"hexValue",{enumerable:true,get:function(){return chunkOM7NOHJF_cjs.r}});Object.defineProperty(exports,"matrixValue",{enumerable:true,get:function(){return chunkOM7NOHJF_cjs.C}});Object.defineProperty(exports,"numberValue",{enumerable:true,get:function(){return chunkOM7NOHJF_cjs.n}});Object.defineProperty(exports,"rangeValue",{enumerable:true,get:function(){return chunkOM7NOHJF_cjs.F}});Object.defineProperty(exports,"rowVectorValue",{enumerable:true,get:function(){return chunkOM7NOHJF_cjs.D}});Object.defineProperty(exports,"stringValue",{enumerable:true,get:function(){return chunkOM7NOHJF_cjs.t}});Object.defineProperty(exports,"uomValue",{enumerable:true,get:function(){return chunkOM7NOHJF_cjs.u}});exports.VMCheckpointer=l;//# sourceMappingURL=vm.cjs.map
1
+ 'use strict';var chunkLI6LYJDA_cjs=require('./chunk-LI6LYJDA.cjs');require('./chunk-HG4NPDN5.cjs');var chunkFESR6PZI_cjs=require('./chunk-FESR6PZI.cjs');require('./chunk-OBZJKZ2F.cjs'),require('./chunk-SF5QVUEI.cjs'),require('./chunk-ABVDKMNF.cjs'),require('./chunk-TLG7VZRX.cjs'),require('./chunk-WFT3XUSH.cjs'),require('./chunk-EQNKDTMX.cjs'),require('./chunk-E4HAKNBQ.cjs');var chunkS3SPDK6N_cjs=require('./chunk-S3SPDK6N.cjs');require('./chunk-PHWIO4P3.cjs'),require('./chunk-EZKR44MA.cjs'),require('./chunk-6SYU4MH7.cjs');var l=class{constructor(t){this.checkpoints=[];this.vm=t;}snapshot(t,n,e){if(e.length===0)return null;let r=this.checkpoints.length>0?this.checkpoints[this.checkpoints.length-1]:null,o=Object.create(r?.variables??null),i=Object.create(r?.functions??null);for(let s of e){if(this.vm.hasUserFunction(s)){let p=this.vm.getUserFunction(s);p&&(i[s]=p);continue}let u=this.vm.getVar(s);u!==void 0&&(o[s]=u);}let c={lineNumber:t,lineId:n,variables:o,functions:i,parent:r};return this.checkpoints.push(c),c}restoreTo(t){let n=this.getNearestCheckpoint(t);if(!n){this.vm.reset();return}let e=[],r=n;for(;r;)e.unshift(r),r=r.parent;this.vm.reset();for(let o of e){for(let i of Object.keys(o.variables))this.vm.setVar(i,o.variables[i]);for(let i of Object.keys(o.functions)){let c=o.functions[i];this.vm.defineUserFunction(c.name,c.params,c.program);}}}getNearestCheckpoint(t){let n=null;for(let e of this.checkpoints)if(e.lineNumber<=t)n=e;else break;return n}getCheckpointAt(t){return this.checkpoints.find(n=>n.lineNumber===t)}getAllCheckpoints(){return this.checkpoints}lookupVariable(t){if(this.checkpoints.length===0)return;let e=this.checkpoints[this.checkpoints.length-1].variables;for(;e;){if(Object.prototype.hasOwnProperty.call(e,t))return e[t];e=Object.getPrototypeOf(e);}}clear(){this.checkpoints=[];}get count(){return this.checkpoints.length}get isEmpty(){return this.checkpoints.length===0}get vmInstance(){return this.vm}};Object.defineProperty(exports,"DependencyGraph",{enumerable:true,get:function(){return chunkLI6LYJDA_cjs.a}});Object.defineProperty(exports,"ScopeManager",{enumerable:true,get:function(){return chunkLI6LYJDA_cjs.b}});Object.defineProperty(exports,"createVM",{enumerable:true,get:function(){return chunkLI6LYJDA_cjs.c}});Object.defineProperty(exports,"executeBytecode",{enumerable:true,get:function(){return chunkLI6LYJDA_cjs.d}});Object.defineProperty(exports,"OpRegistry",{enumerable:true,get:function(){return chunkFESR6PZI_cjs.v}});Object.defineProperty(exports,"allocatePluginFunctionIndex",{enumerable:true,get:function(){return chunkFESR6PZI_cjs.E}});Object.defineProperty(exports,"binaryOp",{enumerable:true,get:function(){return chunkFESR6PZI_cjs.u}});Object.defineProperty(exports,"builtinFunctions",{enumerable:true,get:function(){return chunkFESR6PZI_cjs.C}});Object.defineProperty(exports,"pluginFunctionIndexFor",{enumerable:true,get:function(){return chunkFESR6PZI_cjs.F}});Object.defineProperty(exports,"pluginFunctionRegistry",{enumerable:true,get:function(){return chunkFESR6PZI_cjs.D}});Object.defineProperty(exports,"sharedOpRegistry",{enumerable:true,get:function(){return chunkFESR6PZI_cjs.w}});Object.defineProperty(exports,"unifyUom",{enumerable:true,get:function(){return chunkFESR6PZI_cjs.j}});Object.defineProperty(exports,"Value",{enumerable:true,get:function(){return chunkS3SPDK6N_cjs.m}});Object.defineProperty(exports,"ValueType",{enumerable:true,get:function(){return chunkS3SPDK6N_cjs.g}});Object.defineProperty(exports,"bigIntValue",{enumerable:true,get:function(){return chunkS3SPDK6N_cjs.s}});Object.defineProperty(exports,"chargeAllocation",{enumerable:true,get:function(){return chunkS3SPDK6N_cjs.c}});Object.defineProperty(exports,"checkAllocation",{enumerable:true,get:function(){return chunkS3SPDK6N_cjs.d}});Object.defineProperty(exports,"checkedArray",{enumerable:true,get:function(){return chunkS3SPDK6N_cjs.e}});Object.defineProperty(exports,"colVectorValue",{enumerable:true,get:function(){return chunkS3SPDK6N_cjs.E}});Object.defineProperty(exports,"hexValue",{enumerable:true,get:function(){return chunkS3SPDK6N_cjs.r}});Object.defineProperty(exports,"matrixValue",{enumerable:true,get:function(){return chunkS3SPDK6N_cjs.C}});Object.defineProperty(exports,"numberValue",{enumerable:true,get:function(){return chunkS3SPDK6N_cjs.n}});Object.defineProperty(exports,"rangeValue",{enumerable:true,get:function(){return chunkS3SPDK6N_cjs.F}});Object.defineProperty(exports,"rowVectorValue",{enumerable:true,get:function(){return chunkS3SPDK6N_cjs.D}});Object.defineProperty(exports,"stringValue",{enumerable:true,get:function(){return chunkS3SPDK6N_cjs.t}});Object.defineProperty(exports,"uomValue",{enumerable:true,get:function(){return chunkS3SPDK6N_cjs.u}});exports.VMCheckpointer=l;//# sourceMappingURL=vm.cjs.map
2
2
  //# sourceMappingURL=vm.cjs.map
package/dist/vm.d.cts CHANGED
@@ -1,11 +1,11 @@
1
- export { B as Bytecode, D as DependencyGraph, E as ExpressionRecord, L as LineExecutionContext, O as OpRegistry, S as ScopeManager, V as VM, a as allocatePluginFunctionIndex, b as builtinFunctions, c as createVM, e as executeBytecode, p as pluginFunctionIndexFor, d as pluginFunctionRegistry, s as sharedOpRegistry } from './VMBuiltins-BkKzhj6C.cjs';
2
- import { V as Value } from './Value-BYHw-x7q.cjs';
3
- export { M as MatrixData, a as MatrixEntry, R as RangeData, b as ValueType, c as bigIntValue, d as colVectorValue, h as hexValue, m as matrixValue, n as numberValue, r as rangeValue, e as rowVectorValue, s as stringValue, u as uomValue } from './Value-BYHw-x7q.cjs';
4
- export { V as VMCheckpoint, a as VMCheckpointer } from './VMCheckpoints-WdUQrdc9.cjs';
1
+ export { B as Bytecode, D as DependencyGraph, E as ExpressionRecord, L as LineExecutionContext, O as OpRegistry, S as ScopeManager, V as VM, a as allocatePluginFunctionIndex, b as builtinFunctions, c as createVM, e as executeBytecode, p as pluginFunctionIndexFor, d as pluginFunctionRegistry, s as sharedOpRegistry } from './VMBuiltins-JCavlQUj.cjs';
2
+ import { V as Value } from './Value-2TIKi-YL.cjs';
3
+ export { M as MatrixData, a as MatrixEntry, R as RangeData, b as ValueType, c as bigIntValue, d as colVectorValue, h as hexValue, m as matrixValue, n as numberValue, r as rangeValue, e as rowVectorValue, s as stringValue, u as uomValue } from './Value-2TIKi-YL.cjs';
4
+ export { V as VMCheckpoint, a as VMCheckpointer } from './VMCheckpoints-BxPzmdu0.cjs';
5
5
  import './BytecodeBuilder-DSWKZi4f.cjs';
6
6
  import './CalendarBackend-MdS3Bb4P.cjs';
7
- import './EngineError-CqGtaT_v.cjs';
8
- import './pipeline-BYkKNpql.cjs';
7
+ import './EngineError-Bm4OYmw8.cjs';
8
+ import './pipeline-Bum6y1B9.cjs';
9
9
 
10
10
  /**
11
11
  * The ceiling on how much memory one evaluation is allowed to ask for.
package/dist/vm.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- export { B as Bytecode, D as DependencyGraph, E as ExpressionRecord, L as LineExecutionContext, O as OpRegistry, S as ScopeManager, V as VM, a as allocatePluginFunctionIndex, b as builtinFunctions, c as createVM, e as executeBytecode, p as pluginFunctionIndexFor, d as pluginFunctionRegistry, s as sharedOpRegistry } from './VMBuiltins-Du9y8sEo.js';
2
- import { V as Value } from './Value-BYHw-x7q.js';
3
- export { M as MatrixData, a as MatrixEntry, R as RangeData, b as ValueType, c as bigIntValue, d as colVectorValue, h as hexValue, m as matrixValue, n as numberValue, r as rangeValue, e as rowVectorValue, s as stringValue, u as uomValue } from './Value-BYHw-x7q.js';
4
- export { V as VMCheckpoint, a as VMCheckpointer } from './VMCheckpoints-gvy_yxYh.js';
1
+ export { B as Bytecode, D as DependencyGraph, E as ExpressionRecord, L as LineExecutionContext, O as OpRegistry, S as ScopeManager, V as VM, a as allocatePluginFunctionIndex, b as builtinFunctions, c as createVM, e as executeBytecode, p as pluginFunctionIndexFor, d as pluginFunctionRegistry, s as sharedOpRegistry } from './VMBuiltins-qgzA6qGi.js';
2
+ import { V as Value } from './Value-2TIKi-YL.js';
3
+ export { M as MatrixData, a as MatrixEntry, R as RangeData, b as ValueType, c as bigIntValue, d as colVectorValue, h as hexValue, m as matrixValue, n as numberValue, r as rangeValue, e as rowVectorValue, s as stringValue, u as uomValue } from './Value-2TIKi-YL.js';
4
+ export { V as VMCheckpoint, a as VMCheckpointer } from './VMCheckpoints-DjjE92mf.js';
5
5
  import './BytecodeBuilder-DSWKZi4f.js';
6
6
  import './CalendarBackend-MdS3Bb4P.js';
7
- import './EngineError-CqGtaT_v.js';
8
- import './pipeline-Cl7KW8CB.js';
7
+ import './EngineError-Bm4OYmw8.js';
8
+ import './pipeline-DOo3KHaq.js';
9
9
 
10
10
  /**
11
11
  * The ceiling on how much memory one evaluation is allowed to ask for.
package/dist/vm.js CHANGED
@@ -1,2 +1,2 @@
1
- export{a as DependencyGraph,b as ScopeManager,c as createVM,d as executeBytecode}from'./chunk-AF6NDOIE.js';import'./chunk-JP4JMQOG.js';export{v as OpRegistry,E as allocatePluginFunctionIndex,u as binaryOp,C as builtinFunctions,F as pluginFunctionIndexFor,D as pluginFunctionRegistry,w as sharedOpRegistry,j as unifyUom}from'./chunk-OE2DBN4K.js';import'./chunk-3ZGFAE3Q.js';import'./chunk-PTXUWGRR.js';import'./chunk-TZYMXNIB.js';import'./chunk-HFKDWQUL.js';import'./chunk-KH4QXKLT.js';import'./chunk-NQFCXLEF.js';import'./chunk-J4K72CQN.js';export{m as Value,g as ValueType,s as bigIntValue,c as chargeAllocation,d as checkAllocation,e as checkedArray,E as colVectorValue,r as hexValue,C as matrixValue,n as numberValue,F as rangeValue,D as rowVectorValue,t as stringValue,u as uomValue}from'./chunk-X5K72MBV.js';import'./chunk-BWTVJD5L.js';import'./chunk-PRSXXDTA.js';import'./chunk-RELMEWY6.js';var l=class{constructor(t){this.checkpoints=[];this.vm=t;}snapshot(t,n,e){if(e.length===0)return null;let r=this.checkpoints.length>0?this.checkpoints[this.checkpoints.length-1]:null,o=Object.create(r?.variables??null),i=Object.create(r?.functions??null);for(let s of e){if(this.vm.hasUserFunction(s)){let p=this.vm.getUserFunction(s);p&&(i[s]=p);continue}let u=this.vm.getVar(s);u!==void 0&&(o[s]=u);}let c={lineNumber:t,lineId:n,variables:o,functions:i,parent:r};return this.checkpoints.push(c),c}restoreTo(t){let n=this.getNearestCheckpoint(t);if(!n){this.vm.reset();return}let e=[],r=n;for(;r;)e.unshift(r),r=r.parent;this.vm.reset();for(let o of e){for(let i of Object.keys(o.variables))this.vm.setVar(i,o.variables[i]);for(let i of Object.keys(o.functions)){let c=o.functions[i];this.vm.defineUserFunction(c.name,c.params,c.program);}}}getNearestCheckpoint(t){let n=null;for(let e of this.checkpoints)if(e.lineNumber<=t)n=e;else break;return n}getCheckpointAt(t){return this.checkpoints.find(n=>n.lineNumber===t)}getAllCheckpoints(){return this.checkpoints}lookupVariable(t){if(this.checkpoints.length===0)return;let e=this.checkpoints[this.checkpoints.length-1].variables;for(;e;){if(Object.prototype.hasOwnProperty.call(e,t))return e[t];e=Object.getPrototypeOf(e);}}clear(){this.checkpoints=[];}get count(){return this.checkpoints.length}get isEmpty(){return this.checkpoints.length===0}get vmInstance(){return this.vm}};export{l as VMCheckpointer};//# sourceMappingURL=vm.js.map
1
+ export{a as DependencyGraph,b as ScopeManager,c as createVM,d as executeBytecode}from'./chunk-4ASM522I.js';import'./chunk-JP4JMQOG.js';export{v as OpRegistry,E as allocatePluginFunctionIndex,u as binaryOp,C as builtinFunctions,F as pluginFunctionIndexFor,D as pluginFunctionRegistry,w as sharedOpRegistry,j as unifyUom}from'./chunk-INMJ7ZXL.js';import'./chunk-X2GQAKL2.js';import'./chunk-PICFFFJV.js';import'./chunk-TZYMXNIB.js';import'./chunk-HFKDWQUL.js';import'./chunk-4MD5L23F.js';import'./chunk-EOO6M65F.js';import'./chunk-J4K72CQN.js';export{m as Value,g as ValueType,s as bigIntValue,c as chargeAllocation,d as checkAllocation,e as checkedArray,E as colVectorValue,r as hexValue,C as matrixValue,n as numberValue,F as rangeValue,D as rowVectorValue,t as stringValue,u as uomValue}from'./chunk-O7HF345B.js';import'./chunk-BWTVJD5L.js';import'./chunk-PRSXXDTA.js';import'./chunk-6G2NES2I.js';var l=class{constructor(t){this.checkpoints=[];this.vm=t;}snapshot(t,n,e){if(e.length===0)return null;let r=this.checkpoints.length>0?this.checkpoints[this.checkpoints.length-1]:null,o=Object.create(r?.variables??null),i=Object.create(r?.functions??null);for(let s of e){if(this.vm.hasUserFunction(s)){let p=this.vm.getUserFunction(s);p&&(i[s]=p);continue}let u=this.vm.getVar(s);u!==void 0&&(o[s]=u);}let c={lineNumber:t,lineId:n,variables:o,functions:i,parent:r};return this.checkpoints.push(c),c}restoreTo(t){let n=this.getNearestCheckpoint(t);if(!n){this.vm.reset();return}let e=[],r=n;for(;r;)e.unshift(r),r=r.parent;this.vm.reset();for(let o of e){for(let i of Object.keys(o.variables))this.vm.setVar(i,o.variables[i]);for(let i of Object.keys(o.functions)){let c=o.functions[i];this.vm.defineUserFunction(c.name,c.params,c.program);}}}getNearestCheckpoint(t){let n=null;for(let e of this.checkpoints)if(e.lineNumber<=t)n=e;else break;return n}getCheckpointAt(t){return this.checkpoints.find(n=>n.lineNumber===t)}getAllCheckpoints(){return this.checkpoints}lookupVariable(t){if(this.checkpoints.length===0)return;let e=this.checkpoints[this.checkpoints.length-1].variables;for(;e;){if(Object.prototype.hasOwnProperty.call(e,t))return e[t];e=Object.getPrototypeOf(e);}}clear(){this.checkpoints=[];}get count(){return this.checkpoints.length}get isEmpty(){return this.checkpoints.length===0}get vmInstance(){return this.vm}};export{l as VMCheckpointer};//# sourceMappingURL=vm.js.map
2
2
  //# sourceMappingURL=vm.js.map
package/dist/worker.cjs CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var chunk7DJYS5PO_cjs=require('./chunk-7DJYS5PO.cjs'),chunkMDTIL3UT_cjs=require('./chunk-MDTIL3UT.cjs');require('./chunk-Q7TBBV62.cjs'),require('./chunk-NGBBNL4K.cjs'),require('./chunk-ZVPZQ66D.cjs'),require('./chunk-TTFO4YDP.cjs'),require('./chunk-UNKZ5XRC.cjs'),require('./chunk-HG4NPDN5.cjs');var chunkP43SV4NJ_cjs=require('./chunk-P43SV4NJ.cjs');require('./chunk-R2SZFJTT.cjs');var chunkMZQ3ED6J_cjs=require('./chunk-MZQ3ED6J.cjs');require('./chunk-A755LVPT.cjs');var chunkWQGHJAW2_cjs=require('./chunk-WQGHJAW2.cjs');require('./chunk-5AKT36UK.cjs'),require('./chunk-4DR5RBHQ.cjs'),require('./chunk-UURM7P3P.cjs'),require('./chunk-ZLRJ7TDP.cjs'),require('./chunk-LCYQQFUH.cjs'),require('./chunk-CM2WM5CM.cjs'),require('./chunk-DUFEONVN.cjs'),require('./chunk-ABVDKMNF.cjs'),require('./chunk-TLG7VZRX.cjs');var chunk5TVI2UPZ_cjs=require('./chunk-5TVI2UPZ.cjs'),chunkYWF6C2IO_cjs=require('./chunk-YWF6C2IO.cjs');require('./chunk-A764BY7L.cjs'),require('./chunk-E4HAKNBQ.cjs'),require('./chunk-OM7NOHJF.cjs'),require('./chunk-PHWIO4P3.cjs');var chunkVYQNPCM5_cjs=require('./chunk-VYQNPCM5.cjs');require('./chunk-AGCNMEP2.cjs'),require('./chunk-Y7O4D3BJ.cjs'),require('./chunk-WU7SBKVU.cjs'),require('./chunk-YBQOQTVL.cjs'),require('./chunk-S3DFU33X.cjs'),require('./chunk-J4LSAHCY.cjs'),require('./chunk-EZKR44MA.cjs');var chunkSUAGBRQ7_cjs=require('./chunk-SUAGBRQ7.cjs');function B(e){if(e?.date?.inputOrder!=="locale")return e;let r={...e.date,inputOrder:chunkWQGHJAW2_cjs.h({...chunkVYQNPCM5_cjs.b.date,...e.date}).order};return delete r.inputLocale,{...e,date:r}}var x=class{constructor(r){this.nextId=1;this.pending=new Map;this.resolvedListeners=new Set;this.asyncErrorListeners=new Set;this.terminated=false;this.transport=r,this.transport.onMessage(n=>this.onMessage(n));}init(r){let n=this.nextId++;return new Promise((t,s)=>{this.pending.set(n,{resolve:()=>t(),reject:s}),this.transport.postMessage({kind:"init",id:n,localeCode:r.localeCode,diagnostics:r.diagnostics,config:B(r.config),packages:r.packages,formatting:r.formatting});})}parseDocument(r,n){let{signal:t,...s}=n??{},i=Object.keys(s).length>0?s:void 0;return this.call("parseDocument",[r,i],t)}evaluateLines(r,n){return this.call("evaluateLines",[r],n?.signal)}evaluateExpression(r,n){return this.call("evaluateExpression",[r],n?.signal)}onResolved(r){return this.resolvedListeners.add(r),()=>this.resolvedListeners.delete(r)}onAsyncError(r){return this.asyncErrorListeners.add(r),()=>this.asyncErrorListeners.delete(r)}terminate(){if(this.terminated)return;this.terminated=true;let r=chunk7DJYS5PO_cjs.e();for(let n of this.pending.values())this.unhook(n),n.reject(r);this.pending.clear(),this.resolvedListeners.clear(),this.asyncErrorListeners.clear(),this.transport.terminate();}call(r,n,t){if(this.terminated)return Promise.reject(chunk7DJYS5PO_cjs.e());if(t?.aborted)return Promise.reject(chunk7DJYS5PO_cjs.d(r));let s=this.nextId++;return new Promise((i,l)=>{let c={resolve:i,reject:l};if(t){let p=()=>{this.pending.has(s)&&(this.pending.delete(s),this.transport.postMessage({kind:"cancel",id:s}),l(chunk7DJYS5PO_cjs.d(r)));};c.signal=t,c.onAbort=p,t.addEventListener("abort",p,{once:true});}this.pending.set(s,c),this.transport.postMessage({kind:"request",id:s,method:r,args:n});})}onMessage(r){let n=r;switch(n.kind){case "ready":case "result":{let t=n.kind==="result"?n.value:void 0;this.settle(n.id,s=>s.resolve(t));break}case "error":this.settle(n.id,t=>t.reject(chunk7DJYS5PO_cjs.c(n.error)));break;case "async-update":for(let t of [...this.resolvedListeners])t(n.lines);break;case "async-error":for(let t of [...this.asyncErrorListeners])t({queryKey:n.queryKey,packageId:n.packageId,error:chunk7DJYS5PO_cjs.c(n.error)});break}}settle(r,n){let t=this.pending.get(r);t&&(this.pending.delete(r),this.unhook(t),n(t));}unhook(r){r.signal&&r.onAbort&&r.signal.removeEventListener("abort",r.onAbort);}};async function G(e){let r=new x(e.transport);return await r.init(e),r}function F(e){return e>0?"Infinity":e<0?"-Infinity":"NaN"}function H(e){let r=e.data.map(n=>typeof n=="object"&&n!==null?chunkYWF6C2IO_cjs.R(n):typeof n=="number"&&!Number.isFinite(n)?F(n):n);return {rows:e.rows,cols:e.cols,cells:r,hasSymbolic:e.hasSymbolic}}function m(e,r){let n=e.toNumber(),t={type:e.type,text:chunkP43SV4NJ_cjs.c(e,r),number:Number.isFinite(n)?n:0};Number.isFinite(n)||(t.nonFinite=F(n)),e.unit!==void 0&&(t.unit=e.unit),e.timedOut!==void 0&&(t.timedOut=e.timedOut),e.grain!==void 0&&(t.grain=e.grain),e.zone!==void 0&&(t.zone=e.zone);let s=e.value;if(typeof s=="bigint")t.bigint=s.toString();else if(e.type===7)t.matrix=H(s);else if(e.type===8){let i=s;t.range={min:i.min,max:i.max};}else if(e.type===14){let i=s;t.colour={hex:chunk5TVI2UPZ_cjs.f(i),r:i.r,g:i.g,b:i.b,a:i.a,format:i.format,css:chunk5TVI2UPZ_cjs.g(i)};}else if(e.type===16){let i=s;t.chart={kind:i.kind,points:i.points.map(l=>[l[0],l[1]]),label:i.label,domain:[i.domain[0],i.domain[1]],range:[i.range[0],i.range[1]],...i.expr!==void 0?{expr:i.expr}:{}};}else if(e.type===17){let i=s;t.ipCidr={...i.addr!==void 0?{addr:i.addr}:{},...i.prefix!==void 0?{prefix:i.prefix}:{},text:chunkP43SV4NJ_cjs.c(e).replace(/^=\s*/,"")};}return t}function q(e,r){return e?m(e,r):null}function J(e,r){return {start:e.start,end:e.end,expression:e.expression,lineNumber:e.lineNumber,columnNumber:e.columnNumber,result:q(e.result,r),error:e.error??null}}function y(e,r){return {lineNumber:e.lineNumber,text:e.text,startPosition:e.startPosition,endPosition:e.endPosition,isEmpty:e.isEmpty,hasInlineSolves:e.hasInlineSolves,inlineSolves:e.inlineSolves.map(n=>J(n,r)),expression:e.expression,result:q(e.result,r),error:e.error}}function R(e,r){let n={lines:e.lines.map(t=>y(t,r)),totalLines:e.totalLines,errors:[...e.errors]};return e.diagnostics!==void 0&&(n.diagnostics=e.diagnostics),n}function $(e,r){if(r===void 0)return e;let n=new Map(e.map(s=>[s.name,s])),t=[];for(let s of r){let i=n.get(s);if(!i)throw chunkSUAGBRQ7_cjs.c.config(chunk7DJYS5PO_cjs.a.WORKER_UNKNOWN_PACKAGE,`No package named "${s}" is available in this worker runtime`,{name:s,available:[...n.keys()]});t.push(i);}return t}function Q(e,r={}){let n=r.packages??chunkMZQ3ED6J_cjs.z,t=null,s,i=new Map,l=new Map,c=null,p=null,g=o=>e.postMessage(o),E=(o,a)=>{g({kind:"error",id:o,error:chunk7DJYS5PO_cjs.b(chunkSUAGBRQ7_cjs.d(a))});},D=o=>{let a=new Map;return o.method==="parseDocument"?o.args[0].split(`
2
- `).forEach((u,d)=>a.set(d+1,u)):o.method==="evaluateLines"?o.args[0].forEach((u,d)=>a.set(d+1,u)):a.set(-1,o.args[0]),a},V=(o,a)=>{if(a.type==="error"){g({kind:"async-error",queryKey:a.queryKey,packageId:a.packageId,error:chunk7DJYS5PO_cjs.b(chunkSUAGBRQ7_cjs.d(a.error))});return}let u=[];for(let d of a.lineNumbers){let f=l.get(d);if(f!==void 0)try{let T=o.evaluateLine(d,f);T&&u.push({lineNumber:d,value:m(T,s)});}catch{}}u.length>0&&g({kind:"async-update",lines:u});},U=o=>{p?.();let a=o.getEventStream().getReader();p=()=>{a.cancel();},(async()=>{try{for(;;){let{done:u,value:d}=await a.read();if(u)return;V(o,d);}}catch{}})();},j=o=>{try{let a=$(n,o.packages);t=new chunkMDTIL3UT_cjs.o({locale:o.localeCode??"en",diagnostics:o.diagnostics??!1,config:o.config,packages:a,calendar:r.calendar}),s=r.calendar?{...o.formatting??chunkP43SV4NJ_cjs.a,calendar:r.calendar}:o.formatting,U(t),g({kind:"ready",id:o.id});}catch(a){E(o.id,a);}},K=(o,a)=>{let{method:u,args:d}=a;switch(u){case "parseDocument":return R(o.parseDocument(d[0],d[1]),s);case "evaluateLines":return o.evaluateLines(d[0]).map(f=>y(f,s));case "evaluateExpression":return m(o.evaluateExpression(d[0]),s);default:throw chunkSUAGBRQ7_cjs.c.execution(chunk7DJYS5PO_cjs.a.WORKER_UNKNOWN_METHOD,`The worker runtime has no method named "${String(u)}"`,{method:u})}},_=o=>{let a=t;if(!a){E(o.id,chunkSUAGBRQ7_cjs.c.execution(chunk7DJYS5PO_cjs.a.WORKER_NOT_INITIALISED,"The worker received a request before its engine finished initialising"));return}c?.abort();let u=new AbortController;c=u,l=D(o),i.set(o.id,u),a.setKeystrokeSignal(u.signal);try{let d=K(a,o);g({kind:"result",id:o.id,value:d});}catch(d){E(o.id,d);}finally{i.delete(o.id),a.setKeystrokeSignal(null);}};return e.onMessage(o=>{let a=o;switch(a.kind){case "init":j(a);break;case "request":_(a);break;case "cancel":i.get(a.id)?.abort();break}}),()=>{p?.(),p=null,c?.abort(),c=null,l=new Map;for(let o of i.values())o.abort();i.clear(),t?.clear(),t=null,e.terminate();}}function X(e){return typeof globalThis.structuredClone=="function"?globalThis.structuredClone(e):JSON.parse(JSON.stringify(e))}function Y(){let e=null,r=null,n=true,t=(l,c)=>{let p=X(c);queueMicrotask(()=>{n&&l()?.(p);});};return {client:{postMessage:l=>t(()=>r,l),onMessage:l=>{e=l;},terminate:()=>{n=false;}},host:{postMessage:l=>t(()=>e,l),onMessage:l=>{r=l;},terminate:()=>{n=false;}}}}function Z(e){return {postMessage:r=>e.postMessage(r),onMessage:r=>{let n=t=>r(t.data);typeof e.addEventListener=="function"?e.addEventListener("message",n):e.onmessage=n,e.start?.();},terminate:()=>{e.terminate?.(),e.close?.();}}}function ee(e){return {postMessage:r=>e.postMessage(r),onMessage:r=>{e.on("message",n=>r(n));},terminate:()=>{e.terminate?.(),e.close?.();}}}exports.createLinkedTransports=Y;exports.createWorkerEngine=G;exports.eventTargetTransport=Z;exports.messagePortTransport=ee;exports.serializeParsedLine=y;exports.serializeParsingResult=R;exports.serializeValue=m;exports.startWorkerRuntime=Q;//# sourceMappingURL=worker.cjs.map
1
+ 'use strict';var chunkHSTGWWU2_cjs=require('./chunk-HSTGWWU2.cjs'),chunk4M3FZRGL_cjs=require('./chunk-4M3FZRGL.cjs');require('./chunk-P5YWBIIU.cjs'),require('./chunk-NGBBNL4K.cjs'),require('./chunk-R3W53ZMP.cjs'),require('./chunk-TTFO4YDP.cjs'),require('./chunk-LI6LYJDA.cjs'),require('./chunk-HG4NPDN5.cjs');var chunkQOOTRUY7_cjs=require('./chunk-QOOTRUY7.cjs');require('./chunk-R2SZFJTT.cjs');var chunk7CRVRPV7_cjs=require('./chunk-7CRVRPV7.cjs');require('./chunk-ZSXQP7PD.cjs');var chunkM4UC2PB6_cjs=require('./chunk-M4UC2PB6.cjs');require('./chunk-K3PZ66XR.cjs'),require('./chunk-YV4GDW5A.cjs'),require('./chunk-UURM7P3P.cjs'),require('./chunk-GDLYXRMA.cjs'),require('./chunk-ZLRJ7TDP.cjs'),require('./chunk-FESR6PZI.cjs'),require('./chunk-OBZJKZ2F.cjs'),require('./chunk-SF5QVUEI.cjs'),require('./chunk-ABVDKMNF.cjs'),require('./chunk-TLG7VZRX.cjs');var chunk5TVI2UPZ_cjs=require('./chunk-5TVI2UPZ.cjs'),chunkWFT3XUSH_cjs=require('./chunk-WFT3XUSH.cjs');require('./chunk-EQNKDTMX.cjs'),require('./chunk-E4HAKNBQ.cjs'),require('./chunk-S3SPDK6N.cjs'),require('./chunk-PHWIO4P3.cjs');var chunkHPV4CKCC_cjs=require('./chunk-HPV4CKCC.cjs');require('./chunk-3MG7VIPL.cjs'),require('./chunk-Y7O4D3BJ.cjs'),require('./chunk-72J5V7SN.cjs'),require('./chunk-YBQOQTVL.cjs'),require('./chunk-S3DFU33X.cjs'),require('./chunk-J4LSAHCY.cjs'),require('./chunk-EZKR44MA.cjs');var chunk6SYU4MH7_cjs=require('./chunk-6SYU4MH7.cjs');function B(e){if(e?.date?.inputOrder!=="locale")return e;let r={...e.date,inputOrder:chunkM4UC2PB6_cjs.h({...chunkHPV4CKCC_cjs.b.date,...e.date}).order};return delete r.inputLocale,{...e,date:r}}var x=class{constructor(r){this.nextId=1;this.pending=new Map;this.resolvedListeners=new Set;this.asyncErrorListeners=new Set;this.terminated=false;this.transport=r,this.transport.onMessage(n=>this.onMessage(n));}init(r){let n=this.nextId++;return new Promise((t,s)=>{this.pending.set(n,{resolve:()=>t(),reject:s}),this.transport.postMessage({kind:"init",id:n,localeCode:r.localeCode,diagnostics:r.diagnostics,config:B(r.config),packages:r.packages,formatting:r.formatting});})}parseDocument(r,n){let{signal:t,...s}=n??{},i=Object.keys(s).length>0?s:void 0;return this.call("parseDocument",[r,i],t)}evaluateLines(r,n){return this.call("evaluateLines",[r],n?.signal)}evaluateExpression(r,n){return this.call("evaluateExpression",[r],n?.signal)}onResolved(r){return this.resolvedListeners.add(r),()=>this.resolvedListeners.delete(r)}onAsyncError(r){return this.asyncErrorListeners.add(r),()=>this.asyncErrorListeners.delete(r)}terminate(){if(this.terminated)return;this.terminated=true;let r=chunkHSTGWWU2_cjs.e();for(let n of this.pending.values())this.unhook(n),n.reject(r);this.pending.clear(),this.resolvedListeners.clear(),this.asyncErrorListeners.clear(),this.transport.terminate();}call(r,n,t){if(this.terminated)return Promise.reject(chunkHSTGWWU2_cjs.e());if(t?.aborted)return Promise.reject(chunkHSTGWWU2_cjs.d(r));let s=this.nextId++;return new Promise((i,l)=>{let c={resolve:i,reject:l};if(t){let p=()=>{this.pending.has(s)&&(this.pending.delete(s),this.transport.postMessage({kind:"cancel",id:s}),l(chunkHSTGWWU2_cjs.d(r)));};c.signal=t,c.onAbort=p,t.addEventListener("abort",p,{once:true});}this.pending.set(s,c),this.transport.postMessage({kind:"request",id:s,method:r,args:n});})}onMessage(r){let n=r;switch(n.kind){case "ready":case "result":{let t=n.kind==="result"?n.value:void 0;this.settle(n.id,s=>s.resolve(t));break}case "error":this.settle(n.id,t=>t.reject(chunkHSTGWWU2_cjs.c(n.error)));break;case "async-update":for(let t of [...this.resolvedListeners])t(n.lines);break;case "async-error":for(let t of [...this.asyncErrorListeners])t({queryKey:n.queryKey,packageId:n.packageId,error:chunkHSTGWWU2_cjs.c(n.error)});break}}settle(r,n){let t=this.pending.get(r);t&&(this.pending.delete(r),this.unhook(t),n(t));}unhook(r){r.signal&&r.onAbort&&r.signal.removeEventListener("abort",r.onAbort);}};async function G(e){let r=new x(e.transport);return await r.init(e),r}function F(e){return e>0?"Infinity":e<0?"-Infinity":"NaN"}function H(e){let r=e.data.map(n=>typeof n=="object"&&n!==null?chunkWFT3XUSH_cjs.R(n):typeof n=="number"&&!Number.isFinite(n)?F(n):n);return {rows:e.rows,cols:e.cols,cells:r,hasSymbolic:e.hasSymbolic}}function m(e,r){let n=e.toNumber(),t={type:e.type,text:chunkQOOTRUY7_cjs.c(e,r),number:Number.isFinite(n)?n:0};Number.isFinite(n)||(t.nonFinite=F(n)),e.unit!==void 0&&(t.unit=e.unit),e.timedOut!==void 0&&(t.timedOut=e.timedOut),e.grain!==void 0&&(t.grain=e.grain),e.zone!==void 0&&(t.zone=e.zone);let s=e.value;if(typeof s=="bigint")t.bigint=s.toString();else if(e.type===7)t.matrix=H(s);else if(e.type===8){let i=s;t.range={min:i.min,max:i.max};}else if(e.type===14){let i=s;t.colour={hex:chunk5TVI2UPZ_cjs.f(i),r:i.r,g:i.g,b:i.b,a:i.a,format:i.format,css:chunk5TVI2UPZ_cjs.g(i)};}else if(e.type===16){let i=s;t.chart={kind:i.kind,points:i.points.map(l=>[l[0],l[1]]),label:i.label,domain:[i.domain[0],i.domain[1]],range:[i.range[0],i.range[1]],...i.expr!==void 0?{expr:i.expr}:{}};}else if(e.type===17){let i=s;t.ipCidr={...i.addr!==void 0?{addr:i.addr}:{},...i.prefix!==void 0?{prefix:i.prefix}:{},text:chunkQOOTRUY7_cjs.c(e).replace(/^=\s*/,"")};}return t}function q(e,r){return e?m(e,r):null}function J(e,r){return {start:e.start,end:e.end,expression:e.expression,lineNumber:e.lineNumber,columnNumber:e.columnNumber,result:q(e.result,r),error:e.error??null}}function y(e,r){return {lineNumber:e.lineNumber,text:e.text,startPosition:e.startPosition,endPosition:e.endPosition,isEmpty:e.isEmpty,hasInlineSolves:e.hasInlineSolves,inlineSolves:e.inlineSolves.map(n=>J(n,r)),expression:e.expression,result:q(e.result,r),error:e.error}}function R(e,r){let n={lines:e.lines.map(t=>y(t,r)),totalLines:e.totalLines,errors:[...e.errors]};return e.diagnostics!==void 0&&(n.diagnostics=e.diagnostics),n}function $(e,r){if(r===void 0)return e;let n=new Map(e.map(s=>[s.name,s])),t=[];for(let s of r){let i=n.get(s);if(!i)throw chunk6SYU4MH7_cjs.c.config(chunkHSTGWWU2_cjs.a.WORKER_UNKNOWN_PACKAGE,`No package named "${s}" is available in this worker runtime`,{name:s,available:[...n.keys()]});t.push(i);}return t}function Q(e,r={}){let n=r.packages??chunk7CRVRPV7_cjs.z,t=null,s,i=new Map,l=new Map,c=null,p=null,g=o=>e.postMessage(o),E=(o,a)=>{g({kind:"error",id:o,error:chunkHSTGWWU2_cjs.b(chunk6SYU4MH7_cjs.d(a))});},D=o=>{let a=new Map;return o.method==="parseDocument"?o.args[0].split(`
2
+ `).forEach((u,d)=>a.set(d+1,u)):o.method==="evaluateLines"?o.args[0].forEach((u,d)=>a.set(d+1,u)):a.set(-1,o.args[0]),a},V=(o,a)=>{if(a.type==="error"){g({kind:"async-error",queryKey:a.queryKey,packageId:a.packageId,error:chunkHSTGWWU2_cjs.b(chunk6SYU4MH7_cjs.d(a.error))});return}let u=[];for(let d of a.lineNumbers){let f=l.get(d);if(f!==void 0)try{let T=o.evaluateLine(d,f);T&&u.push({lineNumber:d,value:m(T,s)});}catch{}}u.length>0&&g({kind:"async-update",lines:u});},U=o=>{p?.();let a=o.getEventStream().getReader();p=()=>{a.cancel();},(async()=>{try{for(;;){let{done:u,value:d}=await a.read();if(u)return;V(o,d);}}catch{}})();},j=o=>{try{let a=$(n,o.packages);t=new chunk4M3FZRGL_cjs.o({locale:o.localeCode??"en",diagnostics:o.diagnostics??!1,config:o.config,packages:a,calendar:r.calendar}),s=r.calendar?{...o.formatting??chunkQOOTRUY7_cjs.a,calendar:r.calendar}:o.formatting,U(t),g({kind:"ready",id:o.id});}catch(a){E(o.id,a);}},K=(o,a)=>{let{method:u,args:d}=a;switch(u){case "parseDocument":return R(o.parseDocument(d[0],d[1]),s);case "evaluateLines":return o.evaluateLines(d[0]).map(f=>y(f,s));case "evaluateExpression":return m(o.evaluateExpression(d[0]),s);default:throw chunk6SYU4MH7_cjs.c.execution(chunkHSTGWWU2_cjs.a.WORKER_UNKNOWN_METHOD,`The worker runtime has no method named "${String(u)}"`,{method:u})}},_=o=>{let a=t;if(!a){E(o.id,chunk6SYU4MH7_cjs.c.execution(chunkHSTGWWU2_cjs.a.WORKER_NOT_INITIALISED,"The worker received a request before its engine finished initialising"));return}c?.abort();let u=new AbortController;c=u,l=D(o),i.set(o.id,u),a.setKeystrokeSignal(u.signal);try{let d=K(a,o);g({kind:"result",id:o.id,value:d});}catch(d){E(o.id,d);}finally{i.delete(o.id),a.setKeystrokeSignal(null);}};return e.onMessage(o=>{let a=o;switch(a.kind){case "init":j(a);break;case "request":_(a);break;case "cancel":i.get(a.id)?.abort();break}}),()=>{p?.(),p=null,c?.abort(),c=null,l=new Map;for(let o of i.values())o.abort();i.clear(),t?.clear(),t=null,e.terminate();}}function X(e){return typeof globalThis.structuredClone=="function"?globalThis.structuredClone(e):JSON.parse(JSON.stringify(e))}function Y(){let e=null,r=null,n=true,t=(l,c)=>{let p=X(c);queueMicrotask(()=>{n&&l()?.(p);});};return {client:{postMessage:l=>t(()=>r,l),onMessage:l=>{e=l;},terminate:()=>{n=false;}},host:{postMessage:l=>t(()=>e,l),onMessage:l=>{r=l;},terminate:()=>{n=false;}}}}function Z(e){return {postMessage:r=>e.postMessage(r),onMessage:r=>{let n=t=>r(t.data);typeof e.addEventListener=="function"?e.addEventListener("message",n):e.onmessage=n,e.start?.();},terminate:()=>{e.terminate?.(),e.close?.();}}}function ee(e){return {postMessage:r=>e.postMessage(r),onMessage:r=>{e.on("message",n=>r(n));},terminate:()=>{e.terminate?.(),e.close?.();}}}exports.createLinkedTransports=Y;exports.createWorkerEngine=G;exports.eventTargetTransport=Z;exports.messagePortTransport=ee;exports.serializeParsedLine=y;exports.serializeParsingResult=R;exports.serializeValue=m;exports.startWorkerRuntime=Q;//# sourceMappingURL=worker.cjs.map
3
3
  //# sourceMappingURL=worker.cjs.map