@faicad/faijs 0.33.1 → 0.35.2

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 (392) hide show
  1. package/dist/api/api-namespace.d.ts +14 -14
  2. package/dist/api/api-namespace.d.ts.map +1 -1
  3. package/dist/api/api-namespace.js +40 -14
  4. package/dist/api/api-namespace.js.map +1 -1
  5. package/dist/api/appearance.d.ts +47 -6
  6. package/dist/api/appearance.d.ts.map +1 -1
  7. package/dist/api/appearance.js.map +1 -1
  8. package/dist/api/assembly/solve-tree.d.ts +1 -0
  9. package/dist/api/assembly/solve-tree.d.ts.map +1 -1
  10. package/dist/api/assembly/solve-tree.js +42 -17
  11. package/dist/api/assembly/solve-tree.js.map +1 -1
  12. package/dist/api/assembly/solve.d.ts +1 -0
  13. package/dist/api/assembly/solve.d.ts.map +1 -1
  14. package/dist/api/assembly/solve.js.map +1 -1
  15. package/dist/api/assembly/solvers/global-solver.d.ts.map +1 -1
  16. package/dist/api/assembly/solvers/global-solver.js +130 -23
  17. package/dist/api/assembly/solvers/global-solver.js.map +1 -1
  18. package/dist/api/assembly/solvers/pose-from-delta.d.ts +9 -0
  19. package/dist/api/assembly/solvers/pose-from-delta.d.ts.map +1 -1
  20. package/dist/api/assembly/solvers/pose-from-delta.js +23 -0
  21. package/dist/api/assembly/solvers/pose-from-delta.js.map +1 -1
  22. package/dist/api/assembly/solvers/types.d.ts +20 -2
  23. package/dist/api/assembly/solvers/types.d.ts.map +1 -1
  24. package/dist/api/assembly/solvers/types.js.map +1 -1
  25. package/dist/api/chamfer.d.ts +7 -4
  26. package/dist/api/chamfer.d.ts.map +1 -1
  27. package/dist/api/chamfer.js +57 -13
  28. package/dist/api/chamfer.js.map +1 -1
  29. package/dist/api/draft.d.ts +7 -4
  30. package/dist/api/draft.d.ts.map +1 -1
  31. package/dist/api/draft.js +11 -6
  32. package/dist/api/draft.js.map +1 -1
  33. package/dist/api/edge-ref.d.ts +4 -4
  34. package/dist/api/edge-ref.js +4 -4
  35. package/dist/api/edge-ref.js.map +1 -1
  36. package/dist/api/extrude.d.ts +10 -6
  37. package/dist/api/extrude.d.ts.map +1 -1
  38. package/dist/api/extrude.js +50 -25
  39. package/dist/api/extrude.js.map +1 -1
  40. package/dist/api/face-ref.d.ts +4 -4
  41. package/dist/api/face-ref.js +4 -4
  42. package/dist/api/face-ref.js.map +1 -1
  43. package/dist/api/feature-repair.d.ts +6 -3
  44. package/dist/api/feature-repair.d.ts.map +1 -1
  45. package/dist/api/feature-repair.js +12 -7
  46. package/dist/api/feature-repair.js.map +1 -1
  47. package/dist/api/fillet-variable.d.ts +6 -2
  48. package/dist/api/fillet-variable.d.ts.map +1 -1
  49. package/dist/api/fillet-variable.js +24 -6
  50. package/dist/api/fillet-variable.js.map +1 -1
  51. package/dist/api/fillet.d.ts +7 -4
  52. package/dist/api/fillet.d.ts.map +1 -1
  53. package/dist/api/fillet.js +45 -12
  54. package/dist/api/fillet.js.map +1 -1
  55. package/dist/api/helix.d.ts +13 -13
  56. package/dist/api/helix.d.ts.map +1 -1
  57. package/dist/api/helix.js +19 -24
  58. package/dist/api/helix.js.map +1 -1
  59. package/dist/api/import-brep.d.ts +10 -18
  60. package/dist/api/import-brep.d.ts.map +1 -1
  61. package/dist/api/import-brep.js +17 -25
  62. package/dist/api/import-brep.js.map +1 -1
  63. package/dist/api/import-step.d.ts +10 -15
  64. package/dist/api/import-step.d.ts.map +1 -1
  65. package/dist/api/import-step.js +24 -29
  66. package/dist/api/import-step.js.map +1 -1
  67. package/dist/api/index.js +2 -2
  68. package/dist/api/index.js.map +1 -1
  69. package/dist/api/internal/export-members.js.map +1 -1
  70. package/dist/api/loft-advanced.d.ts +4 -0
  71. package/dist/api/loft-advanced.d.ts.map +1 -1
  72. package/dist/api/loft-advanced.js +4 -0
  73. package/dist/api/loft-advanced.js.map +1 -1
  74. package/dist/api/loft.d.ts +5 -3
  75. package/dist/api/loft.d.ts.map +1 -1
  76. package/dist/api/loft.js +5 -3
  77. package/dist/api/loft.js.map +1 -1
  78. package/dist/api/meta.d.ts +42 -6
  79. package/dist/api/meta.d.ts.map +1 -1
  80. package/dist/api/meta.js.map +1 -1
  81. package/dist/api/punch-hole.d.ts +5 -2
  82. package/dist/api/punch-hole.d.ts.map +1 -1
  83. package/dist/api/punch-hole.js +4 -1
  84. package/dist/api/punch-hole.js.map +1 -1
  85. package/dist/api/replicate.d.ts +4 -5
  86. package/dist/api/replicate.d.ts.map +1 -1
  87. package/dist/api/replicate.js +4 -5
  88. package/dist/api/replicate.js.map +1 -1
  89. package/dist/api/selectors-to-refs.d.ts +83 -0
  90. package/dist/api/selectors-to-refs.d.ts.map +1 -0
  91. package/dist/api/selectors-to-refs.js +211 -0
  92. package/dist/api/selectors-to-refs.js.map +1 -0
  93. package/dist/api/shell.d.ts +17 -8
  94. package/dist/api/shell.d.ts.map +1 -1
  95. package/dist/api/shell.js +45 -15
  96. package/dist/api/shell.js.map +1 -1
  97. package/dist/api/sketch-on-face.d.ts +12 -6
  98. package/dist/api/sketch-on-face.d.ts.map +1 -1
  99. package/dist/api/sketch-on-face.js +31 -4
  100. package/dist/api/sketch-on-face.js.map +1 -1
  101. package/dist/api/sketch-on-plane.d.ts +3 -0
  102. package/dist/api/sketch-on-plane.d.ts.map +1 -1
  103. package/dist/api/sketch-on-plane.js +3 -0
  104. package/dist/api/sketch-on-plane.js.map +1 -1
  105. package/dist/api/sketch-on-surface.d.ts +4 -1
  106. package/dist/api/sketch-on-surface.d.ts.map +1 -1
  107. package/dist/api/sketch-on-surface.js +4 -1
  108. package/dist/api/sketch-on-surface.js.map +1 -1
  109. package/dist/api/view/view-projection.d.ts.map +1 -1
  110. package/dist/api/view/view-projection.js +9 -2
  111. package/dist/api/view/view-projection.js.map +1 -1
  112. package/dist/brep/brep-chain.js +2 -2
  113. package/dist/brep/brep-chain.js.map +1 -1
  114. package/dist/brep/brep-ops.d.ts +1 -1
  115. package/dist/brep/brep-ops.js +1 -1
  116. package/dist/brep/brep-ops.js.map +1 -1
  117. package/dist/brep/engine/adapters/brep-mock.d.ts.map +1 -1
  118. package/dist/brep/engine/adapters/brep-mock.js +45 -0
  119. package/dist/brep/engine/adapters/brep-mock.js.map +1 -1
  120. package/dist/brep/engine/primitives.d.ts +87 -3
  121. package/dist/brep/engine/primitives.d.ts.map +1 -1
  122. package/dist/brep/engine/primitives.js +1 -1
  123. package/dist/brep/engine/primitives.js.map +1 -1
  124. package/dist/brep/engine/registry.d.ts +33 -7
  125. package/dist/brep/engine/registry.d.ts.map +1 -1
  126. package/dist/brep/engine/registry.js +47 -16
  127. package/dist/brep/engine/registry.js.map +1 -1
  128. package/dist/brep/handle-bridge.d.ts +14 -15
  129. package/dist/brep/handle-bridge.d.ts.map +1 -1
  130. package/dist/brep/handle-bridge.js +35 -15
  131. package/dist/brep/handle-bridge.js.map +1 -1
  132. package/dist/brep/primitives-brep.js +2 -2
  133. package/dist/brep/primitives-brep.js.map +1 -1
  134. package/dist/brep/text/text-to-solid.d.ts +40 -3
  135. package/dist/brep/text/text-to-solid.d.ts.map +1 -1
  136. package/dist/brep/text/text-to-solid.js +104 -24
  137. package/dist/brep/text/text-to-solid.js.map +1 -1
  138. package/dist/brepkit-kernel/brepkitKernel.d.ts +2 -2
  139. package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
  140. package/dist/brepkit-kernel/brepkitKernel.js +315 -36
  141. package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
  142. package/dist/brepkit-kernel/brepkitWasm.js +7 -7
  143. package/dist/brepkit-kernel/brepkitWasm.js.map +1 -1
  144. package/dist/brepkit-kernel/multi-version-test.d.ts +2 -2
  145. package/dist/brepkit-kernel/multi-version-test.d.ts.map +1 -1
  146. package/dist/brepkit-kernel/multi-version-test.js +6 -6
  147. package/dist/brepkit-kernel/multi-version-test.js.map +1 -1
  148. package/dist/browser.d.ts +2 -3
  149. package/dist/browser.d.ts.map +1 -1
  150. package/dist/browser.js +1 -2
  151. package/dist/browser.js.map +1 -1
  152. package/dist/cad-runtime/admit-compat-lib.d.ts +9 -1
  153. package/dist/cad-runtime/admit-compat-lib.d.ts.map +1 -1
  154. package/dist/cad-runtime/admit-compat-lib.js +11 -1
  155. package/dist/cad-runtime/admit-compat-lib.js.map +1 -1
  156. package/dist/cad-runtime/browser-lib-loader.d.ts +16 -11
  157. package/dist/cad-runtime/browser-lib-loader.d.ts.map +1 -1
  158. package/dist/cad-runtime/browser-lib-loader.js +16 -8
  159. package/dist/cad-runtime/browser-lib-loader.js.map +1 -1
  160. package/dist/cad-runtime/direct-executor.d.ts +62 -5
  161. package/dist/cad-runtime/direct-executor.d.ts.map +1 -1
  162. package/dist/cad-runtime/direct-executor.js +617 -42
  163. package/dist/cad-runtime/direct-executor.js.map +1 -1
  164. package/dist/cad-runtime/interp/closure.d.ts +3 -2
  165. package/dist/cad-runtime/interp/closure.d.ts.map +1 -1
  166. package/dist/cad-runtime/interp/closure.js.map +1 -1
  167. package/dist/cad-runtime/interp/env.d.ts +9 -6
  168. package/dist/cad-runtime/interp/env.d.ts.map +1 -1
  169. package/dist/cad-runtime/interp/env.js +4 -2
  170. package/dist/cad-runtime/interp/env.js.map +1 -1
  171. package/dist/cad-runtime/lib-decl.d.ts +121 -0
  172. package/dist/cad-runtime/lib-decl.d.ts.map +1 -0
  173. package/dist/cad-runtime/lib-decl.js +100 -0
  174. package/dist/cad-runtime/lib-decl.js.map +1 -0
  175. package/dist/cad-runtime/ports.d.ts +12 -0
  176. package/dist/cad-runtime/ports.d.ts.map +1 -1
  177. package/dist/cad-runtime/ports.js.map +1 -1
  178. package/dist/cad-runtime/runtime.d.ts +59 -5
  179. package/dist/cad-runtime/runtime.d.ts.map +1 -1
  180. package/dist/cad-runtime/runtime.js +237 -18
  181. package/dist/cad-runtime/runtime.js.map +1 -1
  182. package/dist/extra/browser.d.ts +9 -0
  183. package/dist/extra/browser.d.ts.map +1 -0
  184. package/dist/extra/browser.js +9 -0
  185. package/dist/extra/browser.js.map +1 -0
  186. package/dist/extra/editor-ops.d.ts +22 -0
  187. package/dist/extra/editor-ops.d.ts.map +1 -0
  188. package/dist/extra/editor-ops.js +21 -0
  189. package/dist/extra/editor-ops.js.map +1 -0
  190. package/dist/extra/extras/svg-extrude.d.ts +45 -0
  191. package/dist/extra/extras/svg-extrude.d.ts.map +1 -0
  192. package/dist/extra/extras/svg-extrude.js +110 -0
  193. package/dist/extra/extras/svg-extrude.js.map +1 -0
  194. package/dist/extra/extras/text-cjk.d.ts +36 -0
  195. package/dist/extra/extras/text-cjk.d.ts.map +1 -0
  196. package/dist/extra/extras/text-cjk.js +86 -0
  197. package/dist/extra/extras/text-cjk.js.map +1 -0
  198. package/dist/extra/extras/text-geometry.d.ts +69 -0
  199. package/dist/extra/extras/text-geometry.d.ts.map +1 -0
  200. package/dist/extra/extras/text-geometry.js +188 -0
  201. package/dist/extra/extras/text-geometry.js.map +1 -0
  202. package/dist/extra/index.d.ts +40 -0
  203. package/dist/extra/index.d.ts.map +1 -0
  204. package/dist/extra/index.js +40 -0
  205. package/dist/extra/index.js.map +1 -0
  206. package/dist/extra/mesh/drill-hole/DrillHoleCore.d.ts +94 -0
  207. package/dist/extra/mesh/drill-hole/DrillHoleCore.d.ts.map +1 -0
  208. package/dist/extra/mesh/drill-hole/DrillHoleCore.js +282 -0
  209. package/dist/extra/mesh/drill-hole/DrillHoleCore.js.map +1 -0
  210. package/dist/extra/mesh/drill-hole/drill-types.d.ts +34 -0
  211. package/dist/extra/mesh/drill-hole/drill-types.d.ts.map +1 -0
  212. package/dist/extra/mesh/drill-hole/drill-types.js +7 -0
  213. package/dist/extra/mesh/drill-hole/drill-types.js.map +1 -0
  214. package/dist/extra/mesh/engrave-decoration.d.ts +42 -0
  215. package/dist/extra/mesh/engrave-decoration.d.ts.map +1 -0
  216. package/dist/extra/mesh/engrave-decoration.js +39 -0
  217. package/dist/extra/mesh/engrave-decoration.js.map +1 -0
  218. package/dist/extra/mesh/fai_drill.d.ts +21 -0
  219. package/dist/extra/mesh/fai_drill.d.ts.map +1 -0
  220. package/dist/extra/mesh/fai_drill.js +89 -0
  221. package/dist/extra/mesh/fai_drill.js.map +1 -0
  222. package/dist/extra/mesh/fai_extrude.d.ts +24 -0
  223. package/dist/extra/mesh/fai_extrude.d.ts.map +1 -0
  224. package/dist/extra/mesh/fai_extrude.js +42 -0
  225. package/dist/extra/mesh/fai_extrude.js.map +1 -0
  226. package/dist/extra/mesh/fai_split.d.ts +164 -0
  227. package/dist/extra/mesh/fai_split.d.ts.map +1 -0
  228. package/dist/extra/mesh/fai_split.js +269 -0
  229. package/dist/extra/mesh/fai_split.js.map +1 -0
  230. package/dist/extra/mesh/primitives.d.ts +29 -0
  231. package/dist/extra/mesh/primitives.d.ts.map +1 -0
  232. package/dist/extra/mesh/primitives.js +41 -0
  233. package/dist/extra/mesh/primitives.js.map +1 -0
  234. package/dist/extra/op-names.d.ts +37 -0
  235. package/dist/extra/op-names.d.ts.map +1 -0
  236. package/dist/extra/op-names.js +46 -0
  237. package/dist/extra/op-names.js.map +1 -0
  238. package/dist/extra/ops/compound.d.ts +140 -0
  239. package/dist/extra/ops/compound.d.ts.map +1 -0
  240. package/dist/extra/ops/compound.js +167 -0
  241. package/dist/extra/ops/compound.js.map +1 -0
  242. package/dist/extra/ops/copy.d.ts +40 -0
  243. package/dist/extra/ops/copy.d.ts.map +1 -0
  244. package/dist/extra/ops/copy.js +83 -0
  245. package/dist/extra/ops/copy.js.map +1 -0
  246. package/dist/extra/ops/fai_drill.d.ts +51 -0
  247. package/dist/extra/ops/fai_drill.d.ts.map +1 -0
  248. package/dist/extra/ops/fai_drill.js +233 -0
  249. package/dist/extra/ops/fai_drill.js.map +1 -0
  250. package/dist/extra/ops/fai_extrude.d.ts +36 -0
  251. package/dist/extra/ops/fai_extrude.d.ts.map +1 -0
  252. package/dist/extra/ops/fai_extrude.js +84 -0
  253. package/dist/extra/ops/fai_extrude.js.map +1 -0
  254. package/dist/extra/ops/fai_split.d.ts +46 -0
  255. package/dist/extra/ops/fai_split.d.ts.map +1 -0
  256. package/dist/extra/ops/fai_split.js +235 -0
  257. package/dist/extra/ops/fai_split.js.map +1 -0
  258. package/dist/extra/ops/load.d.ts +49 -0
  259. package/dist/extra/ops/load.d.ts.map +1 -0
  260. package/dist/extra/ops/load.js +385 -0
  261. package/dist/extra/ops/load.js.map +1 -0
  262. package/dist/extra/ops/svg-extrude.d.ts +32 -0
  263. package/dist/extra/ops/svg-extrude.d.ts.map +1 -0
  264. package/dist/extra/ops/svg-extrude.js +74 -0
  265. package/dist/extra/ops/svg-extrude.js.map +1 -0
  266. package/dist/extra/ops/text.d.ts +34 -0
  267. package/dist/extra/ops/text.d.ts.map +1 -0
  268. package/dist/extra/ops/text.js +100 -0
  269. package/dist/extra/ops/text.js.map +1 -0
  270. package/dist/geometry2d/bridge/lift-on-plane.d.ts +8 -5
  271. package/dist/geometry2d/bridge/lift-on-plane.d.ts.map +1 -1
  272. package/dist/geometry2d/bridge/lift-on-plane.js +8 -5
  273. package/dist/geometry2d/bridge/lift-on-plane.js.map +1 -1
  274. package/dist/index.d.ts +6 -2
  275. package/dist/index.d.ts.map +1 -1
  276. package/dist/index.js +8 -2
  277. package/dist/index.js.map +1 -1
  278. package/dist/lang/symbol-table.d.ts +3 -3
  279. package/dist/lang/symbol-table.generated.d.ts +10 -0
  280. package/dist/lang/symbol-table.generated.d.ts.map +1 -1
  281. package/dist/lang/symbol-table.generated.js +10 -0
  282. package/dist/lang/symbol-table.generated.js.map +1 -1
  283. package/dist/lang/symbol-table.js +3 -3
  284. package/dist/lang/symbol-table.js.map +1 -1
  285. package/dist/math3d/index.d.ts +1 -1
  286. package/dist/math3d/index.js +1 -1
  287. package/dist/math3d/index.js.map +1 -1
  288. package/dist/mesh/engrave.d.ts +2 -3
  289. package/dist/mesh/engrave.d.ts.map +1 -1
  290. package/dist/mesh/engrave.js +4 -11
  291. package/dist/mesh/engrave.js.map +1 -1
  292. package/dist/mesh/index.d.ts +0 -2
  293. package/dist/mesh/index.d.ts.map +1 -1
  294. package/dist/mesh/index.js +0 -2
  295. package/dist/mesh/index.js.map +1 -1
  296. package/dist/mesh/primitives.d.ts +1 -1
  297. package/dist/mesh/primitives.js +1 -1
  298. package/dist/mesh/primitives.js.map +1 -1
  299. package/dist/node-host/cli.d.ts +20 -4
  300. package/dist/node-host/cli.d.ts.map +1 -1
  301. package/dist/node-host/cli.js +84 -35
  302. package/dist/node-host/cli.js.map +1 -1
  303. package/dist/node-host/execute-script.d.ts.map +1 -1
  304. package/dist/node-host/execute-script.js +3 -4
  305. package/dist/node-host/execute-script.js.map +1 -1
  306. package/dist/node-host/lib-package-json.d.ts +36 -0
  307. package/dist/node-host/lib-package-json.d.ts.map +1 -0
  308. package/dist/node-host/lib-package-json.js +73 -0
  309. package/dist/node-host/lib-package-json.js.map +1 -0
  310. package/dist/occt-kernel/occt-primitives.d.ts.map +1 -1
  311. package/dist/occt-kernel/occt-primitives.js +41 -0
  312. package/dist/occt-kernel/occt-primitives.js.map +1 -1
  313. package/dist/occt-kernel/occtKernel.d.ts +1 -1
  314. package/dist/occt-kernel/occtKernel.js +1 -1
  315. package/dist/occt-kernel/occtKernel.js.map +1 -1
  316. package/dist/runtime-state.d.ts +28 -1
  317. package/dist/runtime-state.d.ts.map +1 -1
  318. package/dist/runtime-state.js +14 -1
  319. package/dist/runtime-state.js.map +1 -1
  320. package/dist/sdk.d.ts +2 -2
  321. package/dist/sdk.d.ts.map +1 -1
  322. package/dist/sdk.js +11 -2
  323. package/dist/sdk.js.map +1 -1
  324. package/dist/sketch/bspline.d.ts +58 -0
  325. package/dist/sketch/bspline.d.ts.map +1 -0
  326. package/dist/sketch/bspline.js +104 -0
  327. package/dist/sketch/bspline.js.map +1 -0
  328. package/dist/sketch/canonical.d.ts +239 -0
  329. package/dist/sketch/canonical.d.ts.map +1 -0
  330. package/dist/sketch/canonical.js +17 -0
  331. package/dist/sketch/canonical.js.map +1 -0
  332. package/dist/sketch/contour.d.ts +43 -0
  333. package/dist/sketch/contour.d.ts.map +1 -0
  334. package/dist/sketch/contour.js +202 -0
  335. package/dist/sketch/contour.js.map +1 -0
  336. package/dist/sketch/dim-spec.d.ts +32 -0
  337. package/dist/sketch/dim-spec.d.ts.map +1 -0
  338. package/dist/sketch/dim-spec.js +112 -0
  339. package/dist/sketch/dim-spec.js.map +1 -0
  340. package/dist/sketch/faces.d.ts +45 -0
  341. package/dist/sketch/faces.d.ts.map +1 -0
  342. package/dist/sketch/faces.js +108 -0
  343. package/dist/sketch/faces.js.map +1 -0
  344. package/dist/sketch/fcstd-types.d.ts +194 -0
  345. package/dist/sketch/fcstd-types.d.ts.map +1 -0
  346. package/dist/sketch/fcstd-types.js +67 -0
  347. package/dist/sketch/fcstd-types.js.map +1 -0
  348. package/dist/sketch/index.d.ts +46 -0
  349. package/dist/sketch/index.d.ts.map +1 -0
  350. package/dist/sketch/index.js +39 -0
  351. package/dist/sketch/index.js.map +1 -0
  352. package/dist/sketch/node.d.ts +14 -0
  353. package/dist/sketch/node.d.ts.map +1 -0
  354. package/dist/sketch/node.js +43 -0
  355. package/dist/sketch/node.js.map +1 -0
  356. package/dist/sketch/op.d.ts +111 -0
  357. package/dist/sketch/op.d.ts.map +1 -0
  358. package/dist/sketch/op.js +185 -0
  359. package/dist/sketch/op.js.map +1 -0
  360. package/dist/sketch/planegcs-backend.d.ts +69 -0
  361. package/dist/sketch/planegcs-backend.d.ts.map +1 -0
  362. package/dist/sketch/planegcs-backend.js +812 -0
  363. package/dist/sketch/planegcs-backend.js.map +1 -0
  364. package/dist/sketch/project.d.ts +176 -0
  365. package/dist/sketch/project.d.ts.map +1 -0
  366. package/dist/sketch/project.js +656 -0
  367. package/dist/sketch/project.js.map +1 -0
  368. package/dist/sketch/shapes.d.ts +370 -0
  369. package/dist/sketch/shapes.d.ts.map +1 -0
  370. package/dist/sketch/shapes.js +959 -0
  371. package/dist/sketch/shapes.js.map +1 -0
  372. package/dist/sketch/solve.d.ts +21 -0
  373. package/dist/sketch/solve.d.ts.map +1 -0
  374. package/dist/sketch/solve.js +144 -0
  375. package/dist/sketch/solve.js.map +1 -0
  376. package/dist/sketch/solver-loader.d.ts +47 -0
  377. package/dist/sketch/solver-loader.d.ts.map +1 -0
  378. package/dist/sketch/solver-loader.js +77 -0
  379. package/dist/sketch/solver-loader.js.map +1 -0
  380. package/dist/sketch/solver.d.ts +63 -0
  381. package/dist/sketch/solver.d.ts.map +1 -0
  382. package/dist/sketch/solver.js +28 -0
  383. package/dist/sketch/solver.js.map +1 -0
  384. package/dist/sketch/verify.d.ts +53 -0
  385. package/dist/sketch/verify.d.ts.map +1 -0
  386. package/dist/sketch/verify.js +71 -0
  387. package/dist/sketch/verify.js.map +1 -0
  388. package/dist/weapp.d.ts +1 -1
  389. package/dist/weapp.d.ts.map +1 -1
  390. package/dist/weapp.js +1 -1
  391. package/dist/weapp.js.map +1 -1
  392. package/package.json +43 -11
@@ -12,7 +12,9 @@
12
12
  * 被 await 是合法 JS);
13
13
  * - keep/keepHidden 尾随键剥离(行内 keep 由 MetadataExtractor 的 metadata.keep
14
14
  * 表另存,§4.4 消费判定用——执行侧不传);
15
- * - 顶层函数定义提升到 `__ctx.<name>`(函数体 cad 等经命名空间绑定注入);
15
+ * - 顶层函数定义提升到 `__ctx.<name>`(函数体 cad 等经命名空间绑定注入;函数体
16
+ * 引用到的顶层变量/函数经 call-time 守卫 + `let { ... } = __ctx` 解构注入——
17
+ * 约束 1:读顶层 call-time 取值,函数体内赋值写本地副本不落顶层);
16
18
  * - import 行不执行(库装载在 runtime 层;`ns.<binding>` 经命名空间对象访问)。
17
19
  *
18
20
  * 错误定位:单行单元失败记 failedAt({ index, callee, message } + lineNo)。
@@ -49,6 +51,112 @@ function resolveExecBackend(choice) {
49
51
  return new InterpBackend();
50
52
  return new VmBackend();
51
53
  }
54
+ /**
55
+ * F1(2026-10-15):标识符提升的**保护区间**——字符串字面量 / 模板文本 / 注释。
56
+ *
57
+ * 根因:hoistBlockText ② 与 hoistText 用文本级 `\b<name>\b` 全局替换做标识符提升,
58
+ * 不区分代码与字符串。for 循环体内与顶层标识符同名的字符串字面量被改写成
59
+ * `__ctx.<name>`(`parent: 'carrier'` → `'__ctx.carrier'`),装配侧按「父级不存在」
60
+ * 静默挂错父级——animation 钉子 `test/p2-child-ref.test.ts:83-105` 的上游根因。
61
+ *
62
+ * 区间来自 acorn AST(ranges 已开):字符串 Literal 全区间、TemplateLiteral 的
63
+ * quasis(模板**文本**部分;`${…}` 表达式是代码,不保护)、onComment 收集的注释
64
+ * 区间。解析策略与 hoistBlockText 一致(module 直解 → `(function(){ … })` 回退,
65
+ * 放行 break/continue/return);回退包装的前缀长度逐区间扣减,保持原文本基准。
66
+ * 两轮都解析失败(调用方传入的不是合法 JS 片段,如对象方法简写)时返回空数组
67
+ * = 无保护,维持修复前行为。
68
+ */
69
+ function collectHoistProtectedRanges(text) {
70
+ const ranges = [];
71
+ const comments = [];
72
+ const parseOpts = {
73
+ ecmaVersion: 'latest',
74
+ sourceType: 'module',
75
+ locations: false,
76
+ ranges: true,
77
+ onComment: (_block, _text, start, end) => {
78
+ comments.push([start, end]);
79
+ },
80
+ };
81
+ let ast;
82
+ let shift = 0;
83
+ try {
84
+ ast = acornParse(text, parseOpts);
85
+ }
86
+ catch {
87
+ const wrapped = `(function(){ ${text} })`;
88
+ try {
89
+ ast = acornParse(wrapped, parseOpts);
90
+ shift = '(function(){ '.length;
91
+ }
92
+ catch {
93
+ return [];
94
+ }
95
+ }
96
+ const walk = (n) => {
97
+ if (!n || typeof n !== 'object')
98
+ return;
99
+ if (n.type === 'Literal' && typeof n.value === 'string') {
100
+ ranges.push([n.start - shift, n.end - shift]);
101
+ }
102
+ else if (n.type === 'TemplateLiteral') {
103
+ for (const q of n.quasis ?? []) {
104
+ if (typeof q?.start === 'number' && typeof q?.end === 'number') {
105
+ ranges.push([q.start - shift, q.end - shift]);
106
+ }
107
+ }
108
+ }
109
+ for (const k of Object.keys(n)) {
110
+ if (k === 'loc' || k === 'start' || k === 'end' || k === 'range' || k === 'parent' || k === 'type')
111
+ continue;
112
+ const v = n[k];
113
+ if (Array.isArray(v))
114
+ for (const item of v)
115
+ walk(item);
116
+ else if (v && typeof v === 'object')
117
+ walk(v);
118
+ }
119
+ };
120
+ walk(ast);
121
+ for (const [s, e] of comments)
122
+ ranges.push([s - shift, e - shift]);
123
+ return ranges;
124
+ }
125
+ /**
126
+ * F1:带保护区间的顺序文本替换(标识符 / 命名空间提升专用)。
127
+ *
128
+ * `subs` 每条 { re, emit } 依次作用于 text(后者看到前者的输出,与既有顺序替换
129
+ * 语义一致);匹配整体落在保护区间(字符串 / 模板文本 / 注释)内时原样保留。
130
+ * 保护区间按**当前** text 重算(前一条 sub 会改变偏移),text 未变时复用。
131
+ * 无保护区间(解析失败)时退化为普通替换——与修复前完全一致。
132
+ *
133
+ * `re` 必须带 `g` 标志;`emit(groups)` 接收捕获组($1 起),返回替换文本。
134
+ */
135
+ function replaceOutsideProtected(text, subs) {
136
+ let out = text;
137
+ let ranges = [];
138
+ let rangesFor = null;
139
+ for (const sub of subs) {
140
+ if (!sub.re.global)
141
+ throw new Error('replaceOutsideProtected: sub.re must carry the g flag');
142
+ if (rangesFor !== out) {
143
+ ranges = collectHoistProtectedRanges(out);
144
+ rangesFor = out;
145
+ }
146
+ const rr = ranges;
147
+ out = out.replace(sub.re, (...args) => {
148
+ const match = args[0];
149
+ const groups = args.slice(1, -2);
150
+ const offset = args[args.length - 2];
151
+ for (const [s, e] of rr) {
152
+ if (offset >= s && offset + match.length <= e)
153
+ return match;
154
+ }
155
+ return sub.emit(groups);
156
+ });
157
+ }
158
+ return out;
159
+ }
52
160
  /**
53
161
  * DirectExecutor executes `.fai.js` source text directly in the JS VM. Each
54
162
  * top-level statement is transformed mechanically (ctx hoisting + await
@@ -186,7 +294,8 @@ export class DirectExecutor {
186
294
  if (node.type === 'ImportDeclaration')
187
295
  continue;
188
296
  const rawLine = (node?.loc?.start?.line ?? 1) - lineOffset;
189
- const unit = this.transformTopNode(node, parseText, declared, rawLine, lineOffset);
297
+ // 仅取行区间(lineNo/endLine),注入内容不消费——候选全集传空集即可。
298
+ const unit = this.transformTopNode(node, parseText, declared, rawLine, lineOffset, new Set());
190
299
  if (unit)
191
300
  ranges.push({ lineNo: unit.lineNo, endLine: unit.endLine });
192
301
  }
@@ -700,22 +809,100 @@ export class DirectExecutor {
700
809
  }
701
810
  const { nodes, lineOffset, parseText } = this.parseBody(code);
702
811
  const declared = new Set(); // 累积:参数名 + outputs + 函数名
812
+ // 约束 1:函数体外层引用注入的候选全集(逐语句变换前一次预扫)。
813
+ // 不能用逐语句累积的 declared——函数定义在顶层声明之前(前向引用)时该名
814
+ // 尚未入集 → 漏注入 → vm 调用失败而 interp call-time 查 ctx 成功 → 双后端分叉。
815
+ const allCtxNames = this.collectAllCtxNames(nodes);
703
816
  const units = [];
817
+ const seenLines = new Set();
704
818
  for (const node of nodes) {
705
819
  if (node.type === 'ImportDeclaration')
706
820
  continue; // import 行不执行
707
821
  const rawLine = (node?.loc?.start?.line ?? 1) - lineOffset;
708
- const unit = this.transformTopNode(node, parseText, declared, rawLine, lineOffset);
822
+ if (seenLines.has(rawLine)) {
823
+ throw new ParseError(`multiple statements on line ${rawLine}: faijs requires one statement per line (use newline instead of ';')`, rawLine, 'E_SYNTAX');
824
+ }
825
+ seenLines.add(rawLine);
826
+ const unit = this.transformTopNode(node, parseText, declared, rawLine, lineOffset, allCtxNames);
709
827
  if (unit)
710
828
  units.push(unit);
711
829
  }
712
830
  return units;
713
831
  }
714
- transformTopNode(node, code, declared, lineNo, lineOffset) {
832
+ /**
833
+ * 约束 1 候选全集预扫:本脚本全部声明名(含块内声明——vm 的块单元经
834
+ * hoistBlockText 把块内 let/const/function 提升写 ctx,interp 的 root env
835
+ * 块级写入同样落 ctx)∪ 现有 ctx 键(params/imports 预置键 + append 场景
836
+ * 先前执行产出)。不下潜函数体——函数局部量永不入 ctx。
837
+ * 命名空间名从候选剔除(函数体的 ns 绑定由 transformFunction 的 binds 提供)。
838
+ */
839
+ collectAllCtxNames(nodes) {
840
+ const names = new Set(Object.keys(this.ctx));
841
+ const walk = (n) => {
842
+ if (!n || typeof n !== 'object')
843
+ return;
844
+ if (n.type === 'VariableDeclarator') {
845
+ this.collectPatternNames(n.id, names);
846
+ }
847
+ else if (n.type === 'FunctionDeclaration') {
848
+ if (n.id?.type === 'Identifier')
849
+ names.add(n.id.name);
850
+ return; // 函数体内声明是函数局部量,不入 ctx
851
+ }
852
+ else if (n.type === 'FunctionExpression' || n.type === 'ArrowFunctionExpression') {
853
+ return; // 函数表达式/箭头函数体同样不下潜
854
+ }
855
+ for (const k of Object.keys(n)) {
856
+ if (k === 'loc' || k === 'start' || k === 'end' || k === 'range' || k === 'parent' || k === 'type')
857
+ continue;
858
+ const v = n[k];
859
+ if (Array.isArray(v))
860
+ for (const item of v)
861
+ walk(item);
862
+ else if (v && typeof v === 'object')
863
+ walk(v);
864
+ }
865
+ };
866
+ for (const node of nodes)
867
+ walk(node);
868
+ for (const k of Object.keys(this.namespaces)) {
869
+ if (k !== 'contractVersion')
870
+ names.delete(k);
871
+ }
872
+ return names;
873
+ }
874
+ /** 解构模式绑定名收集(Identifier / ObjectPattern / ArrayPattern / AssignmentPattern / RestElement)。 */
875
+ collectPatternNames(pattern, names) {
876
+ if (!pattern || typeof pattern !== 'object')
877
+ return;
878
+ switch (pattern.type) {
879
+ case 'Identifier':
880
+ names.add(pattern.name);
881
+ return;
882
+ case 'ObjectPattern':
883
+ for (const prop of pattern.properties ?? []) {
884
+ if (prop.type === 'Property')
885
+ this.collectPatternNames(prop.value, names);
886
+ else if (prop.type === 'RestElement')
887
+ this.collectPatternNames(prop.argument, names);
888
+ }
889
+ return;
890
+ case 'ArrayPattern':
891
+ for (const el of pattern.elements ?? [])
892
+ this.collectPatternNames(el, names);
893
+ return;
894
+ case 'AssignmentPattern':
895
+ this.collectPatternNames(pattern.left, names);
896
+ return;
897
+ default:
898
+ return;
899
+ }
900
+ }
901
+ transformTopNode(node, code, declared, lineNo, lineOffset, allCtxNames) {
715
902
  let unit;
716
903
  switch (node.type) {
717
904
  case 'FunctionDeclaration':
718
- unit = this.transformFunction(node, code, declared, lineNo);
905
+ unit = this.transformFunction(node, code, declared, lineNo, allCtxNames);
719
906
  break;
720
907
  case 'VariableDeclaration':
721
908
  unit = this.transformVariable(node, code, declared, lineNo);
@@ -786,7 +973,8 @@ export class DirectExecutor {
786
973
  * ctx 键,不会导致错误)。v2 可加 AST walk 精确跳过嵌套作用域。
787
974
  *
788
975
  * 实现策略:先收集块内所有声明名(acorn 扫描 VariableDeclarator + 函数名),
789
- * 再做两步文本替换:① 声明 LHS 提升写 __ctx 赋值;② 自由引用提升走 hoistText。
976
+ * 再做文本替换(⓪ for-of 头 ① 声明 LHS ② 自由引用 ③ 命名空间绑定),全部经
977
+ * replaceOutsideProtected 跳过字符串 / 模板文本 / 注释区间(F1,2026-10-15)。
790
978
  */
791
979
  hoistBlockText(text, declared) {
792
980
  // 收集块内所有声明名(用于引用提升与声明改写)
@@ -844,28 +1032,45 @@ export class DirectExecutor {
844
1032
  // 从提升集合中移除命名空间名(cad 等留在 __ns)
845
1033
  for (const nsName of nsNames)
846
1034
  names.delete(nsName);
847
- // 声明 LHS 改写 + 自由引用提升(词法级,两步替换)
848
- let out = text;
849
- // ⓪ for-of/in 头部声明:`for (const x of/in ...)` → `for (__ctx.x of/in ...)`。
850
- // 步骤①的 `\w+\s*=` 形态匹配不到 of/in 头部,若不先行改写,步骤②会把
851
- // 声明名提升为 `const __ctx.x` → SyntaxError。双前缀由下方修正兜底。
852
- out = out.replace(/\bfor\s*\(\s*(?:const|let)\s+(\w+)\s+(of|in)\b/g, 'for (__ctx.$1 $2 ');
853
- // ① const/let x = ... → __ctx.x = ...(去关键字 + LHS 加 __ctx.)
854
- out = out.replace(/\b(?:const|let)\s+(\w+)\s*=/g, '__ctx.$1 =');
855
- // ② 自由引用提升(与 hoistText 同逻辑,但含块内声明名;排除命名空间名)
856
- for (const name of names) {
857
- out = out.replace(new RegExp(`\\b${name}\\b`, 'g'), `__ctx.${name}`);
1035
+ // ⓪ for-of/in 头部声明 + ① 声明 LHS 改写 + ② 自由引用提升 + ③ 命名空间绑定:
1036
+ // 统一走 replaceOutsideProtected(F1)——落在字符串 / 模板文本 / 注释区间内的
1037
+ // 匹配原样保留。修复前循环体内 `parent: 'carrier'` 被改写成 `'__ctx.carrier'`,
1038
+ // 装配侧静默挂错父级(animation 钉子 test/p2-child-ref.test.ts:83-105)。
1039
+ const subs = [
1040
+ // ⓪ for-of/in 头部声明:`for (const x of/in ...)` → `for (__ctx.x of/in ...)`。
1041
+ // ① 的 `\w+\s*=` 形态匹配不到 of/in 头部,若不先行改写,② 会把声明名
1042
+ // 提升为 `const __ctx.x` → SyntaxError。双前缀由下方修正兜底。
1043
+ {
1044
+ re: /\bfor\s*\(\s*(?:const|let)\s+(\w+)\s+(of|in)\b/g,
1045
+ emit: (g) => `for (__ctx.${g[0]} ${g[1]} `,
1046
+ },
1047
+ // ① const/let x = ... → __ctx.x = ...(去关键字 + LHS 加 __ctx.)
1048
+ { re: /\b(?:const|let)\s+(\w+)\s*=/g, emit: (g) => `__ctx.${g[0]} =` },
1049
+ ];
1050
+ // ② 自由引用提升(与 hoistText 同逻辑,但含块内声明名;排除命名空间名)。
1051
+ // 合并为单趟交替替换:插入的 `__ctx.` 前缀不会让其它名字被二次匹配
1052
+ // (`_`/`.` 都是词边界断点),与逐名顺序替换等价。
1053
+ if (names.size > 0) {
1054
+ subs.push({
1055
+ re: new RegExp(`\\b(${[...names].join('|')})\\b`, 'g'),
1056
+ emit: (g) => `__ctx.${g[0]}`,
1057
+ });
858
1058
  }
859
1059
  // ③ 命名空间名 → __ns.<name> + await 调用
860
- // 块内 cad.xxx(...) 调用需要 await(与扁平行式 emitCall 的 await 语义一致)。
861
- // 分两步:先替换调用形态 `<ns>.<member>(` → `await __ns.<ns>.<member>(`,
862
- // 再替换裸引用 `<ns>`(非成员访问)→ `__ns.<ns>`。
863
- for (const nsName of nsNames) {
1060
+ if (nsNames.size > 0) {
1061
+ const alt = [...nsNames].join('|');
864
1062
  // 调用形态:`cad.box(` → `await __ns.cad.box(`
865
- out = out.replace(new RegExp(`(?<![.\\w])\\b${nsName}\\s*\\.\\s*(\\w+)\\s*\\(`, 'g'), `await __ns.${nsName}.$1(`);
1063
+ subs.push({
1064
+ re: new RegExp(`(?<![.\\w])\\b(${alt})\\s*\\.\\s*(\\w+)\\s*\\(`, 'g'),
1065
+ emit: (g) => `await __ns.${g[0]}.${g[1]}(`,
1066
+ });
866
1067
  // 裸成员访问(非调用):`cad.foo` → `__ns.cad.foo`(非调用不加 await)
867
- out = out.replace(new RegExp(`(?<![.\\w])\\b${nsName}\\s*\\.`, 'g'), `__ns.${nsName}.`);
1068
+ subs.push({
1069
+ re: new RegExp(`(?<![.\\w])\\b(${alt})\\s*\\.`, 'g'),
1070
+ emit: (g) => `__ns.${g[0]}.`,
1071
+ });
868
1072
  }
1073
+ let out = replaceOutsideProtected(text, subs);
869
1074
  // __ctx.__ctx.x → __ctx.x(双前缀修正:LHS 改写后 name 又被提升替换)
870
1075
  out = out.replace(/__ctx\.__ctx\./g, '__ctx.');
871
1076
  // __ns.__ns.cad → __ns.cad(命名空间双前缀修正)
@@ -874,26 +1079,316 @@ export class DirectExecutor {
874
1079
  out = out.replace(/await\s+await\s+__ns\./g, 'await __ns.');
875
1080
  return out;
876
1081
  }
877
- /** 顶层函数提升:`__ctx.<name> = async function <name>(...) { 命名空间绑定; 体 }`。 */
878
- transformFunction(node, code, declared, lineNo) {
1082
+ /** 顶层函数提升:`__ctx.<name> = async function <name>(...) { 命名空间绑定; 外层引用守卫+解构; 体 }`。 */
1083
+ transformFunction(node, code, declared, lineNo, allCtxNames) {
879
1084
  const name = node.id?.name;
880
1085
  if (!name)
881
1086
  throw new ParseError('function declaration must have a name', lineNo, 'E_STATEMENT');
1087
+ // 形参名单(fnParams / 遮蔽集用);默认值等非 Identifier 形参不在此列。
882
1088
  const params = (node.params ?? []).map((p) => p?.name).filter((x) => typeof x === 'string');
883
- const bodyText = code.slice(node.body.start + 1, node.body.end - 1);
1089
+ // 形参保留源文(含默认值表达式)——默认值在 call-time 求值。此前只取 p.name
1090
+ // 会把默认值静默剥离(`d = SIZE` 变成 `d`),与 interp 的 E_UNSUPPORTED_SYNTAX
1091
+ // 形成静默/报错分叉;保留原文后,默认值引用顶层变量在 call 时 ReferenceError
1092
+ // (默认值先于注入解构求值),两后端都失败(constraint 1 差分测试钉住)。
1093
+ let paramsText = (node.params ?? []).map((p) => code.slice(p.start, p.end)).join(', ');
1094
+ let bodyText = code.slice(node.body.start + 1, node.body.end - 1);
884
1095
  const nsNames = Object.keys(this.namespaces).filter((k) => k !== 'contractVersion');
1096
+ // 约束 1 配套:函数体直接作用域内「返回 Promise 的调用」(顶层本机函数 /
1097
+ // 命名空间 op)注入 await——与 emitCall 给顶层调用行加 await 的语义一致。
1098
+ // 缺此注入时 vm 对 `fib(n-1) + fib(n-2)` 之类组合运算拿到 Promise(既有缺陷,
1099
+ // 旧测试只断言不失败未暴露);interp 的 evalExpr 原生 await 无此问题。
1100
+ // 编辑点分两区:参数默认值(签名区)与函数体(体区),右→左插入保持偏移有效。
1101
+ const awaitCalls = this.collectFnAwaitEdits(node, allCtxNames, nsNames);
1102
+ awaitCalls.sort((a, b) => b.start - a.start);
1103
+ const bodyStart = node.body.start + 1;
1104
+ const paramsStart = (node.params?.[0]?.start ?? bodyStart);
1105
+ for (const c of awaitCalls) {
1106
+ if (c.start < bodyStart) {
1107
+ const rel = c.start - paramsStart;
1108
+ paramsText = `${paramsText.slice(0, rel)}await ${paramsText.slice(rel)}`;
1109
+ }
1110
+ else {
1111
+ const rel = c.start - bodyStart;
1112
+ bodyText = `${bodyText.slice(0, rel)}await ${bodyText.slice(rel)}`;
1113
+ }
1114
+ }
885
1115
  const binds = nsNames.map((n) => ` const ${n} = __ns.${n}`).join('\n');
1116
+ // 约束 1:函数体读顶层变量——把函数体引用到的顶层名注入 call-time 守卫 + let 解构。
1117
+ // 读:call-time 取当前值(与 interp 的 ctx 查找同语义,含前向引用);
1118
+ // 写:解构用 let,函数体内赋值写本地副本,不落顶层(与 interp 的 function env
1119
+ // assign 写本地 vars 同语义)。
1120
+ const outerVars = this.collectFnBodyOuterRefs(node, allCtxNames, params, nsNames);
1121
+ const guards = outerVars.map((v) => ` if (!Object.prototype.hasOwnProperty.call(__ctx, '${v}')) throw new ReferenceError('${v} is not defined')`);
886
1122
  const body = [
887
- `__ctx.${name} = async function ${name}(${params.join(', ')}) {`,
1123
+ `__ctx.${name} = async function ${name}(${paramsText}) {`,
888
1124
  binds,
1125
+ ...guards,
1126
+ ...(outerVars.length > 0 ? [` let { ${outerVars.join(', ')} } = __ctx`] : []),
889
1127
  bodyText,
890
1128
  '}',
891
1129
  ].join('\n');
892
- // 本机函数体引用其它本机函数/变量走 __ctx(与顶层一致)
1130
+ // 本机函数体引用其它本机函数/变量走外层引用注入(call-time 读 __ctx,与顶层一致)
893
1131
  declared.add(name);
894
1132
  this.fnParams.set(name, params);
895
1133
  return { lineNo, body, writes: [name], refs: [], callee: name, endLine: 0 };
896
1134
  }
1135
+ /**
1136
+ * 约束 1 配套:收集函数体直接作用域内需要注入 await 的调用节点。
1137
+ * 资格:callee 是 Identifier 且属于候选全集(顶层本机函数),或 callee 是
1138
+ * MemberExpression 且 object 是命名空间名(cad.box 等)。已显式 await 的调用
1139
+ * 不重复注入(其参数里的调用仍递归处理)。不下潜嵌套函数——嵌套 sync function
1140
+ * 体内 await 是 SyntaxError,维持既有行为。参数默认值表达式同样覆盖
1141
+ * (默认值在 async 函数作用域求值,await 合法)。
1142
+ */
1143
+ collectFnAwaitEdits(fnNode, allCtxNames, nsNames) {
1144
+ const edits = [];
1145
+ const ns = new Set(nsNames);
1146
+ const qualifies = (call) => {
1147
+ const callee = call.callee;
1148
+ if (callee?.type === 'Identifier')
1149
+ return allCtxNames.has(callee.name);
1150
+ if (callee?.type === 'MemberExpression' && callee.object?.type === 'Identifier') {
1151
+ return ns.has(callee.object.name);
1152
+ }
1153
+ return false;
1154
+ };
1155
+ const walk = (n) => {
1156
+ if (!n || typeof n !== 'object')
1157
+ return;
1158
+ if (n.type === 'FunctionDeclaration' || n.type === 'FunctionExpression' || n.type === 'ArrowFunctionExpression') {
1159
+ return;
1160
+ }
1161
+ if (n.type === 'AwaitExpression') {
1162
+ // 已显式 await:调用本身不重复注入;实参/实参表达式里的调用仍递归处理
1163
+ const arg = n.argument;
1164
+ if (arg?.type === 'CallExpression') {
1165
+ this.walkChildNodes(arg.callee, walk);
1166
+ for (const a of arg.arguments ?? [])
1167
+ walk(a);
1168
+ }
1169
+ else {
1170
+ walk(arg);
1171
+ }
1172
+ return;
1173
+ }
1174
+ if (n.type === 'CallExpression') {
1175
+ if (qualifies(n))
1176
+ edits.push(n);
1177
+ this.walkChildNodes(n.callee, walk);
1178
+ for (const a of n.arguments ?? [])
1179
+ walk(a);
1180
+ return;
1181
+ }
1182
+ this.walkChildNodes(n, walk);
1183
+ };
1184
+ const stmts = fnNode.body?.type === 'BlockStatement' ? (fnNode.body.body ?? []) : [];
1185
+ for (const s of stmts)
1186
+ walk(s);
1187
+ for (const p of fnNode.params ?? [])
1188
+ walk(p); // 参数默认值表达式(call-time 求值)
1189
+ return edits;
1190
+ } /** 遍历节点全部子节点(跳过元数据键),逐个交给 walk。 */
1191
+ walkChildNodes(n, walk) {
1192
+ if (!n || typeof n !== 'object')
1193
+ return;
1194
+ for (const k of Object.keys(n)) {
1195
+ if (k === 'loc' || k === 'start' || k === 'end' || k === 'range' || k === 'parent' || k === 'type')
1196
+ continue;
1197
+ const v = n[k];
1198
+ if (Array.isArray(v))
1199
+ for (const item of v)
1200
+ walk(item);
1201
+ else if (v && typeof v === 'object')
1202
+ walk(v);
1203
+ }
1204
+ }
1205
+ /**
1206
+ * 约束 1:函数体引用到的顶层名(注入候选)= 候选全集 ∩ 函数体引用集
1207
+ * − 本函数作用域遮蔽集 − 命名空间名。
1208
+ */
1209
+ collectFnBodyOuterRefs(node, allCtxNames, params, nsNames) {
1210
+ const shadow = new Set(params);
1211
+ this.collectFnShadowNames(node.body, shadow);
1212
+ const referenced = new Set();
1213
+ this.collectFnReferences(node.body, referenced);
1214
+ const ns = new Set(nsNames);
1215
+ return [...referenced]
1216
+ .filter((v) => allCtxNames.has(v) && !shadow.has(v) && !ns.has(v))
1217
+ .sort();
1218
+ }
1219
+ /**
1220
+ * 本函数「函数作用域」遮蔽集:决定哪些名不注入(函数体内的同名绑定优先于
1221
+ * 注入的顶层解构)。收集规则:
1222
+ * - 函数体**顶层语句列表**直接声明的 let/const/function 名(函数级作用域);
1223
+ * - 任意块深的 `var` 声明名(var 是函数级;若块内 var 与注入解构同名会
1224
+ * SyntaxError,必须让位);
1225
+ * - 任意块深的 function 声明名(vm 的 new Function 体是 sloppy 模式,块内
1226
+ * function 声明经 Annex B 提升到函数级);
1227
+ * - **不下潜嵌套函数体**:嵌套函数自己的声明只遮蔽它内部,不应阻止外层注入
1228
+ * (否则嵌套函数本地遮蔽会让外层同名顶层引用解析失败)。
1229
+ * 块级 let/const 不入遮蔽集:它们是块作用域,与注入的函数级 `let { ... }`
1230
+ * 并存是合法遮蔽,语义正确。
1231
+ */
1232
+ collectFnShadowNames(body, shadow) {
1233
+ const stmts = body?.type === 'BlockStatement' ? (body.body ?? []) : [];
1234
+ for (const stmt of stmts) {
1235
+ if (stmt.type === 'FunctionDeclaration') {
1236
+ if (stmt.id?.type === 'Identifier')
1237
+ shadow.add(stmt.id.name);
1238
+ }
1239
+ else if (stmt.type === 'VariableDeclaration' && (stmt.kind === 'let' || stmt.kind === 'const')) {
1240
+ for (const d of stmt.declarations ?? [])
1241
+ this.collectPatternNames(d.id, shadow);
1242
+ }
1243
+ }
1244
+ const walk = (n) => {
1245
+ if (!n || typeof n !== 'object')
1246
+ return;
1247
+ if (n.type === 'FunctionDeclaration') {
1248
+ if (n.id?.type === 'Identifier')
1249
+ shadow.add(n.id.name);
1250
+ return; // 不下潜嵌套函数体
1251
+ }
1252
+ if (n.type === 'FunctionExpression' || n.type === 'ArrowFunctionExpression')
1253
+ return;
1254
+ if (n.type === 'VariableDeclaration' && n.kind === 'var') {
1255
+ for (const d of n.declarations ?? [])
1256
+ this.collectPatternNames(d.id, shadow);
1257
+ }
1258
+ for (const k of Object.keys(n)) {
1259
+ if (k === 'loc' || k === 'start' || k === 'end' || k === 'range' || k === 'parent' || k === 'type')
1260
+ continue;
1261
+ const v = n[k];
1262
+ if (Array.isArray(v))
1263
+ for (const item of v)
1264
+ walk(item);
1265
+ else if (v && typeof v === 'object')
1266
+ walk(v);
1267
+ }
1268
+ };
1269
+ for (const stmt of stmts)
1270
+ walk(stmt);
1271
+ }
1272
+ /**
1273
+ * 函数体引用位置标识符收集(含嵌套函数体——嵌套函数引用的顶层名注入到外层
1274
+ * 函数作用域后经闭包可见)。排除声明/绑定位置与非 computed 成员属性、
1275
+ * 非 shorthand 对象键、label。
1276
+ */
1277
+ collectFnReferences(n, refs) {
1278
+ if (!n || typeof n !== 'object')
1279
+ return;
1280
+ switch (n.type) {
1281
+ case 'Identifier':
1282
+ refs.add(n.name);
1283
+ return;
1284
+ case 'MemberExpression':
1285
+ this.collectFnReferences(n.object, refs);
1286
+ if (n.computed)
1287
+ this.collectFnReferences(n.property, refs);
1288
+ return;
1289
+ case 'Property':
1290
+ // shorthand `{ SIZE }`:key 同时是引用;computed `{ [SIZE]: 1 }`:key 是引用;
1291
+ // 普通键 `{ SIZE: 1 }`:key 不是引用。
1292
+ if (n.shorthand || n.computed)
1293
+ this.collectFnReferences(n.key, refs);
1294
+ this.collectFnReferences(n.value, refs);
1295
+ return;
1296
+ case 'VariableDeclaration':
1297
+ for (const d of n.declarations ?? []) {
1298
+ this.walkFnPattern(d.id, refs); // 绑定名跳过;模式内默认值是引用
1299
+ this.collectFnReferences(d.init, refs);
1300
+ }
1301
+ return;
1302
+ case 'FunctionDeclaration':
1303
+ case 'FunctionExpression':
1304
+ case 'ArrowFunctionExpression':
1305
+ for (const p of n.params ?? [])
1306
+ this.walkFnPattern(p, refs);
1307
+ this.collectFnReferences(n.body, refs);
1308
+ return;
1309
+ case 'CatchClause':
1310
+ this.walkFnPattern(n.param, refs);
1311
+ this.collectFnReferences(n.body, refs);
1312
+ return;
1313
+ case 'ForStatement':
1314
+ if (n.init?.type === 'VariableDeclaration') {
1315
+ for (const d of n.init.declarations ?? []) {
1316
+ this.walkFnPattern(d.id, refs);
1317
+ this.collectFnReferences(d.init, refs);
1318
+ }
1319
+ }
1320
+ else {
1321
+ this.collectFnReferences(n.init, refs);
1322
+ }
1323
+ this.collectFnReferences(n.test, refs);
1324
+ this.collectFnReferences(n.update, refs);
1325
+ this.collectFnReferences(n.body, refs);
1326
+ return;
1327
+ case 'ForInStatement':
1328
+ case 'ForOfStatement':
1329
+ if (n.left?.type === 'VariableDeclaration') {
1330
+ for (const d of n.left.declarations ?? [])
1331
+ this.walkFnPattern(d.id, refs);
1332
+ }
1333
+ else {
1334
+ this.walkFnPattern(n.left, refs); // for (x of ...)——左值是赋值目标(引用)
1335
+ }
1336
+ this.collectFnReferences(n.right, refs);
1337
+ this.collectFnReferences(n.body, refs);
1338
+ return;
1339
+ case 'LabeledStatement':
1340
+ this.collectFnReferences(n.body, refs);
1341
+ return;
1342
+ case 'BreakStatement':
1343
+ case 'ContinueStatement':
1344
+ return; // label 不是引用
1345
+ default:
1346
+ for (const k of Object.keys(n)) {
1347
+ if (k === 'loc' || k === 'start' || k === 'end' || k === 'range' || k === 'parent' || k === 'type')
1348
+ continue;
1349
+ const v = n[k];
1350
+ if (Array.isArray(v))
1351
+ for (const item of v)
1352
+ this.collectFnReferences(item, refs);
1353
+ else if (v && typeof v === 'object')
1354
+ this.collectFnReferences(v, refs);
1355
+ }
1356
+ }
1357
+ }
1358
+ /** 绑定模式遍历:绑定名跳过;模式内默认值表达式(AssignmentPattern.right)按引用收集。 */
1359
+ walkFnPattern(n, refs) {
1360
+ if (!n || typeof n !== 'object')
1361
+ return;
1362
+ switch (n.type) {
1363
+ case 'Identifier':
1364
+ return; // 绑定名,不是引用
1365
+ case 'AssignmentPattern':
1366
+ this.collectFnReferences(n.right, refs);
1367
+ this.walkFnPattern(n.left, refs);
1368
+ return;
1369
+ case 'ObjectPattern':
1370
+ for (const prop of n.properties ?? []) {
1371
+ if (prop.type === 'Property') {
1372
+ if (prop.computed)
1373
+ this.collectFnReferences(prop.key, refs);
1374
+ this.walkFnPattern(prop.value, refs);
1375
+ }
1376
+ else if (prop.type === 'RestElement') {
1377
+ this.walkFnPattern(prop.argument, refs);
1378
+ }
1379
+ }
1380
+ return;
1381
+ case 'ArrayPattern':
1382
+ for (const el of n.elements ?? [])
1383
+ this.walkFnPattern(el, refs);
1384
+ return;
1385
+ case 'RestElement':
1386
+ this.walkFnPattern(n.argument, refs);
1387
+ return;
1388
+ default:
1389
+ this.collectFnReferences(n, refs);
1390
+ }
1391
+ }
897
1392
  /** const/let 行:参数(字面量)直接进 ctx;op 行变换调用;派生常量求值。 */
898
1393
  transformVariable(node, code, declared, lineNo) {
899
1394
  if (node.kind !== 'const' && node.kind !== 'let') {
@@ -939,8 +1434,11 @@ export class DirectExecutor {
939
1434
  return { lineNo, body: `__ctx.${name} = ${call}`, writes: [name], refs: this.collectRefs(init), callee: this.calleeOf(init), endLine: 0 };
940
1435
  }
941
1436
  if (init) {
942
- // 参数行(字面量/数组/对象)或派生常量:求值后写入 ctx(引用走 __ctx 提升)
943
- const exprText = this.hoistText(code.slice(init.start, init.end), declared);
1437
+ // 参数行(字面量/数组/对象)或派生常量:AST 变换后写入 ctx。
1438
+ // 用 transformArg 而非整段 hoistText——数组/对象/成员/条件/二元里的命名空间
1439
+ // 调用与 ctx 引用才能正确发射(约束 2:顶层值表达式不得绕过 AST 变换走上
1440
+ // 「文本同构」快路径)。
1441
+ const exprText = this.transformArg(init, code, declared, lineNo);
944
1442
  declared.add(name);
945
1443
  return { lineNo, body: `__ctx.${name} = ${exprText}`, writes: [name], refs: [], callee: undefined, endLine: 0 };
946
1444
  }
@@ -961,8 +1459,8 @@ export class DirectExecutor {
961
1459
  return { lineNo, body: `__ctx.${varName} = ${call}`, writes: [varName], refs: this.collectRefs(init), callee: this.calleeOf(init), endLine: 0 };
962
1460
  }
963
1461
  // 变量→变量重赋值 / 表达式重赋值(`bp = bp2` / `x = a + b`):合法 JS,
964
- // 直接提升自由标识符写回 ctx(A-15 最后写者语义)。
965
- const rhsText = this.hoistText(code.slice(init?.start ?? expr.right.start, expr.right.end), declared);
1462
+ // 走 AST 变换提升自由标识符写回 ctx(A-15 最后写者语义)。
1463
+ const rhsText = this.transformArg(expr.right, code, declared, lineNo);
966
1464
  return { lineNo, body: `__ctx.${varName} = ${rhsText}`, writes: [varName], refs: [], callee: undefined, endLine: 0 };
967
1465
  }
968
1466
  if (expr?.type === 'CallExpression') {
@@ -1112,16 +1610,24 @@ export class DirectExecutor {
1112
1610
  switch (node.type) {
1113
1611
  case 'Literal':
1114
1612
  return JSON.stringify(node.value);
1115
- case 'Identifier':
1613
+ case 'Identifier': {
1116
1614
  // P6/D7 + 2026-10-06:免 import 安全全局(单位常量 MM / INCH / DEGREE / … 以及
1117
1615
  // Math / JSON / Number / Infinity / …)从 globalThis 解析,保持裸名发射;否则会被
1118
1616
  // 写成 `__ctx.Math`(undefined),求值结果静默变错。
1119
1617
  // 已声明变量优先提升为 __ctx.<name>,使同名遮蔽(如 `let Math = 5`)仍按用户变量解析。
1120
1618
  if (declared.has(node.name))
1121
1619
  return `__ctx.${node.name}`;
1620
+ // ctx 键(import 预置 / append 跨文件产出)优先于命名空间——与 emitCall 的
1621
+ // `declared || ctxHas ? __ctx : __ns` 判定同序(约束 2:命名空间绑定不是顶层标识符)。
1622
+ if (this.ctxHas(node.name))
1623
+ return `__ctx.${node.name}`;
1624
+ if (node.name !== 'contractVersion' && Object.hasOwn(this.namespaces, node.name)) {
1625
+ return `__ns.${node.name}`;
1626
+ }
1122
1627
  if (isSafeGlobalIdent(node.name))
1123
1628
  return node.name;
1124
1629
  return `__ctx.${node.name}`;
1630
+ }
1125
1631
  case 'CallExpression':
1126
1632
  return this.emitCall(node, code, declared, lineNo);
1127
1633
  case 'ArrayExpression': {
@@ -1137,6 +1643,12 @@ export class DirectExecutor {
1137
1643
  parts.push(`...${this.transformArg(prop.argument, code, declared, lineNo)}`);
1138
1644
  continue;
1139
1645
  }
1646
+ if (prop.method === true || (prop.kind && prop.kind !== 'init')) {
1647
+ // 方法简写 / getter / setter:AST 没有「属性名: 函数值」的对等再现形态,
1648
+ // 保留原文本片段(内部 ctx/ns 引用仍走 hoistText 提升)。
1649
+ parts.push(this.hoistText(code.slice(prop.start, prop.end), declared));
1650
+ continue;
1651
+ }
1140
1652
  const key = prop.key?.type === 'Identifier' ? prop.key.name
1141
1653
  : prop.key?.type === 'Literal' ? JSON.stringify(String(prop.key.value))
1142
1654
  : null;
@@ -1149,7 +1661,9 @@ export class DirectExecutor {
1149
1661
  return `{ ${parts.join(', ')} }`;
1150
1662
  }
1151
1663
  case 'UnaryExpression':
1152
- return `${node.operator}(${this.transformArg(node.argument, code, declared, lineNo)})`;
1664
+ // 外层括号:AST 发射丢弃了源括号,一元运算符紧邻 `**` 左操作数时 JS 要求
1665
+ // 显式括号(`(-a) ** 2` 合法,`-a ** 2` 抛 SyntaxError)。
1666
+ return `(${node.operator}(${this.transformArg(node.argument, code, declared, lineNo)}))`;
1153
1667
  case 'BinaryExpression':
1154
1668
  case 'LogicalExpression':
1155
1669
  // Parenthesize both operands: the AST emission drops the source's
@@ -1158,24 +1672,85 @@ export class DirectExecutor {
1158
1672
  return `(${this.transformArg(node.left, code, declared, lineNo)} ${node.operator} ${this.transformArg(node.right, code, declared, lineNo)})`;
1159
1673
  case 'ConditionalExpression':
1160
1674
  return `(${this.transformArg(node.test, code, declared, lineNo)} ? ${this.transformArg(node.consequent, code, declared, lineNo)} : ${this.transformArg(node.alternate, code, declared, lineNo)})`;
1161
- case 'MemberExpression':
1162
- return this.hoistText(code.slice(node.start, node.end), declared);
1675
+ case 'TemplateLiteral': {
1676
+ // AST 重建模板:默认分支的 hoistText 会把模板「文本部分」里的标识符也做词边界
1677
+ // 替换(`n=${n}` 的文本 n 与变量 n 同名 → `__ctx.n=${__ctx.n}`,求值错)。
1678
+ const quasis = node.quasis ?? [];
1679
+ const exprs = node.expressions ?? [];
1680
+ let out = '`';
1681
+ for (let i = 0; i < quasis.length; i++) {
1682
+ out += quasis[i].value.raw ?? quasis[i].value.cooked ?? '';
1683
+ if (i < exprs.length)
1684
+ out += '${' + this.transformArg(exprs[i], code, declared, lineNo) + '}';
1685
+ }
1686
+ return out + '`';
1687
+ }
1688
+ case 'SequenceExpression':
1689
+ // AST 序号表达式丢弃了源括号(node.start 不含 `(`),必须补回,
1690
+ // 否则 `x = (1, 2)` 被发射成 `x = 1, 2` → 只赋 1(两后端不一致)。
1691
+ return `(${(node.expressions ?? [])
1692
+ .map((e) => this.transformArg(e, code, declared, lineNo))
1693
+ .join(', ')})`;
1694
+ case 'MemberExpression': {
1695
+ // 可选链保持文本兜底(递归会丢 `?.`)。
1696
+ if (node.optional)
1697
+ return this.hoistText(code.slice(node.start, node.end), declared);
1698
+ // 递归 object(而非整段 hoistText):object 可能是命名空间调用(cad.box(…).x)
1699
+ // 或 ctx 成员链。始终给 object 加括号,保证 await/调用/二元结果的成员访问优先级
1700
+ // 正确——`await __ns.cad.box(x).y` 会先取 `.y` 再 await(错),
1701
+ // 必须 `(await __ns.cad.box(x)).y`(约束 2 的链式形态)。
1702
+ const objText = this.transformArg(node.object, code, declared, lineNo);
1703
+ if (node.computed) {
1704
+ return `(${objText})[${this.transformArg(node.property, code, declared, lineNo)}]`;
1705
+ }
1706
+ return `(${objText}).${node.property.name}`;
1707
+ }
1163
1708
  default:
1164
1709
  return this.hoistText(code.slice(node.start, node.end), declared);
1165
1710
  }
1166
1711
  }
1167
1712
  /** 文本级自由标识符提升:把已声明变量名 + 当前 ctx 键(import 预置/先前执行产出)
1168
- * 替换为 __ctx.<name>(词边界)。含 ctx 键 → append 跨文件引用(D6)与模块命名空间
1169
- * 成员(cfg.OUTX)在实参文本中同样可解析。 */
1713
+ * 替换为 __ctx.<name>(词边界);命名空间绑定(cad + registerLib 注册库)替换为
1714
+ * __ns.<binding>(调用形态前置 await),与 hoistBlockText 步骤 ③ 同语义。
1715
+ *
1716
+ * 含 ctx 键 → append 跨文件引用(D6)与模块命名空间成员(cfg.OUTX)在实参文本中
1717
+ * 同样可解析。命名空间分支不可省:该函数服务顶层**值表达式**(数组/对象/成员/条件/
1718
+ * 二元等非调用 RHS)与 transformArg 的 MemberExpression/default 兜底,这些位置不经过
1719
+ * emitCall,若不在此发射 __ns.<binding>,裸名在 vm 包装(只注入 __ctx/__ns/__isGeom)
1720
+ * 内即是自由标识符 → ReferenceError(`cad is not defined`);而执行同段文本的
1721
+ * interpreter 后端靠 env 的 ns 查找能解析,形成两后端差分(约束 2)。 */
1170
1722
  hoistText(text, declared) {
1171
- let out = text;
1172
1723
  const names = new Set(declared);
1173
1724
  for (const key of Object.keys(this.ctx))
1174
1725
  names.add(key);
1175
- for (const name of names) {
1176
- out = out.replace(new RegExp(`\\b${name}\\b`, 'g'), `__ctx.${name}`);
1726
+ // 命名空间绑定(排除 contractVersion / 已声明同名遮蔽 / 已由 import 预置进 ctx 的绑定)
1727
+ const nsNames = Object.keys(this.namespaces).filter((k) => k !== 'contractVersion' && !names.has(k));
1728
+ // 标识符 + 命名空间提升统一走 replaceOutsideProtected(F1):字符串 / 模板文本 /
1729
+ // 注释区间内的匹配原样保留(修复前实参文本里的 `'carrier'` 会被改写成
1730
+ // `'__ctx.carrier'`,与 hoistBlockText 同根因)。
1731
+ const subs = [];
1732
+ if (names.size > 0) {
1733
+ subs.push({
1734
+ re: new RegExp(`\\b(${[...names].join('|')})\\b`, 'g'),
1735
+ emit: (g) => `__ctx.${g[0]}`,
1736
+ });
1177
1737
  }
1178
- return out;
1738
+ if (nsNames.length > 0) {
1739
+ const alt = nsNames.join('|');
1740
+ // 调用形态:`cad.box(` → `await __ns.cad.box(`
1741
+ subs.push({
1742
+ re: new RegExp(`(?<![.\\w])\\b(${alt})\\s*\\.\\s*(\\w+)\\s*\\(`, 'g'),
1743
+ emit: (g) => `await __ns.${g[0]}.${g[1]}(`,
1744
+ });
1745
+ // 裸成员访问(非调用):`cad.foo` → `__ns.cad.foo`(非调用不加 await)
1746
+ subs.push({
1747
+ re: new RegExp(`(?<![.\\w])\\b(${alt})\\s*\\.`, 'g'),
1748
+ emit: (g) => `__ns.${g[0]}.`,
1749
+ });
1750
+ }
1751
+ const out = replaceOutsideProtected(text, subs);
1752
+ // 双前缀修正(与 hoistBlockText 尾部一致)
1753
+ return out.replace(/__ns\.__ns\./g, '__ns.').replace(/await\s+await\s+__ns\./g, 'await __ns.');
1179
1754
  }
1180
1755
  calleeOf(callNode) {
1181
1756
  if (!callNode || callNode.type !== 'CallExpression')