sourcemonkey 0.0.0-stage → 0.5.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 (367) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -2
  3. package/dist/bytes.js +37 -0
  4. package/dist/channel-placeholder.js +5 -0
  5. package/dist/collection-scan.js +17 -0
  6. package/dist/collections.html +353 -0
  7. package/dist/compare.html +358 -0
  8. package/dist/composed-source.js +205 -0
  9. package/dist/connect-prompt.html +47 -0
  10. package/dist/debug/icons.html +211 -0
  11. package/dist/debug/storage.html +163 -0
  12. package/dist/debug-log.js +75 -0
  13. package/dist/diagnostic-location.js +64 -0
  14. package/dist/eval-hook.js +308 -0
  15. package/dist/extension/background.js +5263 -0
  16. package/dist/extension/channel.js +133 -0
  17. package/dist/extension/code-links.js +187 -0
  18. package/dist/extension/code-tabs.js +460 -0
  19. package/dist/extension/collection-dialog.js +619 -0
  20. package/dist/extension/collection-display.js +322 -0
  21. package/dist/extension/collections.js +2905 -0
  22. package/dist/extension/compare.js +867 -0
  23. package/dist/extension/concurrency.js +186 -0
  24. package/dist/extension/connect-grants.js +109 -0
  25. package/dist/extension/connect-prompt-page.js +70 -0
  26. package/dist/extension/connect-prompt.js +266 -0
  27. package/dist/extension/copy-button.js +63 -0
  28. package/dist/extension/copy-dialog.js +502 -0
  29. package/dist/extension/copy-preference.js +66 -0
  30. package/dist/extension/debug/icons.js +203 -0
  31. package/dist/extension/debug/storage.js +365 -0
  32. package/dist/extension/deep-link.js +77 -0
  33. package/dist/extension/delete-dialog.js +432 -0
  34. package/dist/extension/delete-icon.js +40 -0
  35. package/dist/extension/details-tooltips.js +66 -0
  36. package/dist/extension/directories.js +679 -0
  37. package/dist/extension/export-backup.js +407 -0
  38. package/dist/extension/export-dialog.js +142 -0
  39. package/dist/extension/file-access.js +74 -0
  40. package/dist/extension/file-changes.js +346 -0
  41. package/dist/extension/frame-info.js +85 -0
  42. package/dist/extension/github-provider.js +336 -0
  43. package/dist/extension/glyph.js +84 -0
  44. package/dist/extension/gm-bindings.js +601 -0
  45. package/dist/extension/gm-download.js +419 -0
  46. package/dist/extension/gm-menu.js +228 -0
  47. package/dist/extension/gm-notification.js +141 -0
  48. package/dist/extension/gm-originator-map.js +23 -0
  49. package/dist/extension/gm-tab-data.js +121 -0
  50. package/dist/extension/gm-tab.js +160 -0
  51. package/dist/extension/gm-url-change.js +111 -0
  52. package/dist/extension/gm-url-scheme.js +27 -0
  53. package/dist/extension/gm-values.js +176 -0
  54. package/dist/extension/gm-window-control.js +104 -0
  55. package/dist/extension/gm-xhr-headers.js +333 -0
  56. package/dist/extension/gm-xhr.js +584 -0
  57. package/dist/extension/injector.js +3145 -0
  58. package/dist/extension/install-capture.js +277 -0
  59. package/dist/extension/line-diff.js +233 -0
  60. package/dist/extension/local-copy.js +560 -0
  61. package/dist/extension/local-delete.js +276 -0
  62. package/dist/extension/location-kinds.js +108 -0
  63. package/dist/extension/log-format.js +158 -0
  64. package/dist/extension/managed-changes.js +361 -0
  65. package/dist/extension/managed-items.js +57 -0
  66. package/dist/extension/match-index.js +375 -0
  67. package/dist/extension/missing-scripts.js +66 -0
  68. package/dist/extension/more-menu.js +109 -0
  69. package/dist/extension/move-dialog.js +197 -0
  70. package/dist/extension/offscreen.js +37 -0
  71. package/dist/extension/options.js +504 -0
  72. package/dist/extension/page-heading.js +170 -0
  73. package/dist/extension/page-links.js +199 -0
  74. package/dist/extension/parse-check-client.js +70 -0
  75. package/dist/extension/parse-check.js +161 -0
  76. package/dist/extension/parse-sandbox-host.js +172 -0
  77. package/dist/extension/parse-sandbox.js +175 -0
  78. package/dist/extension/popup-commands-open.js +41 -0
  79. package/dist/extension/popup-view.js +387 -0
  80. package/dist/extension/popup.js +703 -0
  81. package/dist/extension/prism-userscript.js +53 -0
  82. package/dist/extension/refresh-error.js +136 -0
  83. package/dist/extension/refresh-targets.js +160 -0
  84. package/dist/extension/related-versions.js +1144 -0
  85. package/dist/extension/resize-observer-loop.js +19 -0
  86. package/dist/extension/row-cache.js +387 -0
  87. package/dist/extension/script-blobs.js +413 -0
  88. package/dist/extension/script-details.js +658 -0
  89. package/dist/extension/script-enablement.js +285 -0
  90. package/dist/extension/script-identity.js +310 -0
  91. package/dist/extension/script-keys.js +54 -0
  92. package/dist/extension/script-log-id.js +155 -0
  93. package/dist/extension/script-log.js +290 -0
  94. package/dist/extension/script-rejection.js +104 -0
  95. package/dist/extension/script-sites.js +158 -0
  96. package/dist/extension/script-store.js +3507 -0
  97. package/dist/extension/script-updater.js +991 -0
  98. package/dist/extension/script-url-hash.js +61 -0
  99. package/dist/extension/select-all.js +37 -0
  100. package/dist/extension/select-open-guard.js +90 -0
  101. package/dist/extension/site-icon.js +1261 -0
  102. package/dist/extension/sm-dev-link.js +302 -0
  103. package/dist/extension/solo-click.js +58 -0
  104. package/dist/extension/sticky-numbers.js +188 -0
  105. package/dist/extension/storage-breakdown.js +253 -0
  106. package/dist/extension/storage-scan.js +86 -0
  107. package/dist/extension/storage-usage.js +194 -0
  108. package/dist/extension/structural-keys.js +29 -0
  109. package/dist/extension/sw-teardown.js +36 -0
  110. package/dist/extension/tab-status.js +403 -0
  111. package/dist/extension/toolbar-summary.js +105 -0
  112. package/dist/extension/user-scripts-access.js +43 -0
  113. package/dist/extension/userscript.js +3672 -0
  114. package/dist/extension/value-store.js +204 -0
  115. package/dist/extension/version-probe-fetch.js +68 -0
  116. package/dist/extension/worker-client.js +109 -0
  117. package/dist/extension/worker-ops.js +171 -0
  118. package/dist/extension/zip-writer.js +24 -0
  119. package/dist/external-files.js +878 -0
  120. package/dist/file-loader.js +436 -0
  121. package/dist/file-locations.js +439 -0
  122. package/dist/generated-wrappers.js +5 -0
  123. package/dist/github-auth.js +148 -0
  124. package/dist/github-urls.js +46 -0
  125. package/dist/gm-api-catalog.js +217 -0
  126. package/dist/gm-connect.js +273 -0
  127. package/dist/gm-xhr-types.js +5 -0
  128. package/dist/http-read.js +142 -0
  129. package/dist/icons/icon-128.png +0 -0
  130. package/dist/icons/icon-16.png +0 -0
  131. package/dist/icons/icon-48.png +0 -0
  132. package/dist/local-file-overrides.js +558 -0
  133. package/dist/manifest.json +38 -0
  134. package/dist/markup-response.js +126 -0
  135. package/dist/match-targets.js +305 -0
  136. package/dist/menu-captions.js +22 -0
  137. package/dist/offscreen.html +39 -0
  138. package/dist/options.html +197 -0
  139. package/dist/parse-check-protocol.js +51 -0
  140. package/dist/parse-location.js +171 -0
  141. package/dist/parse-sandbox.html +56 -0
  142. package/dist/phase-timing.js +155 -0
  143. package/dist/popup.html +197 -0
  144. package/dist/public-suffixes.js +6957 -0
  145. package/dist/run-context.js +31 -0
  146. package/dist/runtime-messages.js +34 -0
  147. package/dist/sandboxed-page.js +35 -0
  148. package/dist/script-build.js +787 -0
  149. package/dist/script-display.js +383 -0
  150. package/dist/script-icon.js +43 -0
  151. package/dist/script-links.js +204 -0
  152. package/dist/script-source-url.js +214 -0
  153. package/dist/script-world.js +65 -0
  154. package/dist/sm-dev-protocol.js +84 -0
  155. package/dist/source-map.js +177 -0
  156. package/dist/stack-link.js +138 -0
  157. package/dist/styles.css +825 -0
  158. package/dist/unsafe-window-use.js +229 -0
  159. package/dist/url-match.js +734 -0
  160. package/dist/userscript-header.js +248 -0
  161. package/dist/userscript.html +1165 -0
  162. package/dist/vendor/fflate.LICENSE +21 -0
  163. package/dist/vendor/fflate.js +2692 -0
  164. package/dist/vendor/prism/prism-line-numbers.css +1 -0
  165. package/dist/vendor/prism/prism-line-numbers.js +1 -0
  166. package/dist/vendor/prism/prism.css +1 -0
  167. package/dist/vendor/prism/prism.js +1946 -0
  168. package/dist/version-compare.js +141 -0
  169. package/dist/version-probe.js +120 -0
  170. package/lib/build-info.json +1 -0
  171. package/lib/bytes.d.ts +3 -0
  172. package/lib/bytes.js +37 -0
  173. package/lib/channel-placeholder.d.ts +1 -0
  174. package/lib/channel-placeholder.js +5 -0
  175. package/lib/collection-scan.d.ts +8 -0
  176. package/lib/collection-scan.js +17 -0
  177. package/lib/composed-source.d.ts +28 -0
  178. package/lib/composed-source.js +205 -0
  179. package/lib/debug-log.d.ts +9 -0
  180. package/lib/debug-log.js +75 -0
  181. package/lib/diagnostic-location.d.ts +8 -0
  182. package/lib/diagnostic-location.js +64 -0
  183. package/lib/eval-hook.d.ts +34 -0
  184. package/lib/eval-hook.js +308 -0
  185. package/lib/external-files.d.ts +111 -0
  186. package/lib/external-files.js +878 -0
  187. package/lib/file-loader.d.ts +48 -0
  188. package/lib/file-loader.js +436 -0
  189. package/lib/file-locations.d.ts +44 -0
  190. package/lib/file-locations.js +439 -0
  191. package/lib/generated-wrappers.d.ts +11 -0
  192. package/lib/generated-wrappers.js +5 -0
  193. package/lib/github-auth.d.ts +12 -0
  194. package/lib/github-auth.js +148 -0
  195. package/lib/github-urls.d.ts +1 -0
  196. package/lib/github-urls.js +46 -0
  197. package/lib/gm-api-catalog.d.ts +24 -0
  198. package/lib/gm-api-catalog.js +217 -0
  199. package/lib/gm-connect.d.ts +34 -0
  200. package/lib/gm-connect.js +273 -0
  201. package/lib/gm-xhr-types.d.ts +68 -0
  202. package/lib/gm-xhr-types.js +5 -0
  203. package/lib/harness/browser-extensions.d.ts +73 -0
  204. package/lib/harness/browser-extensions.js +285 -0
  205. package/lib/harness/browser-lang.d.ts +20 -0
  206. package/lib/harness/browser-lang.js +86 -0
  207. package/lib/harness/browser-launch.d.ts +14 -0
  208. package/lib/harness/browser-launch.js +184 -0
  209. package/lib/harness/checks.d.ts +110 -0
  210. package/lib/harness/checks.js +321 -0
  211. package/lib/harness/cli.d.ts +2 -0
  212. package/lib/harness/cli.js +2259 -0
  213. package/lib/harness/command-args.d.ts +91 -0
  214. package/lib/harness/command-args.js +369 -0
  215. package/lib/harness/command-lines.d.ts +80 -0
  216. package/lib/harness/command-lines.js +180 -0
  217. package/lib/harness/command-list.d.ts +206 -0
  218. package/lib/harness/command-list.js +1475 -0
  219. package/lib/harness/console-commands.d.ts +463 -0
  220. package/lib/harness/console-commands.js +3216 -0
  221. package/lib/harness/download-watch.d.ts +21 -0
  222. package/lib/harness/download-watch.js +156 -0
  223. package/lib/harness/extension-backend.d.ts +41 -0
  224. package/lib/harness/extension-backend.js +100 -0
  225. package/lib/harness/extension-host.d.ts +112 -0
  226. package/lib/harness/extension-host.js +552 -0
  227. package/lib/harness/extension-launch.d.ts +67 -0
  228. package/lib/harness/extension-launch.js +285 -0
  229. package/lib/harness/extension-link.d.ts +315 -0
  230. package/lib/harness/extension-link.js +607 -0
  231. package/lib/harness/external-manager.d.ts +146 -0
  232. package/lib/harness/external-manager.js +414 -0
  233. package/lib/harness/fixture.d.ts +165 -0
  234. package/lib/harness/fixture.js +461 -0
  235. package/lib/harness/frame-sessions.d.ts +71 -0
  236. package/lib/harness/frame-sessions.js +248 -0
  237. package/lib/harness/frames.d.ts +68 -0
  238. package/lib/harness/frames.js +216 -0
  239. package/lib/harness/help-format.d.ts +17 -0
  240. package/lib/harness/help-format.js +127 -0
  241. package/lib/harness/host.d.ts +352 -0
  242. package/lib/harness/host.js +423 -0
  243. package/lib/harness/index.d.ts +8 -0
  244. package/lib/harness/index.js +10 -0
  245. package/lib/harness/input-file.d.ts +18 -0
  246. package/lib/harness/input-file.js +61 -0
  247. package/lib/harness/json-output.d.ts +565 -0
  248. package/lib/harness/json-output.js +71 -0
  249. package/lib/harness/manager-actions.d.ts +21 -0
  250. package/lib/harness/manager-actions.js +129 -0
  251. package/lib/harness/manager-commands.d.ts +142 -0
  252. package/lib/harness/manager-commands.js +1196 -0
  253. package/lib/harness/manager-fetch.d.ts +33 -0
  254. package/lib/harness/manager-fetch.js +239 -0
  255. package/lib/harness/managers.d.ts +24 -0
  256. package/lib/harness/managers.js +27 -0
  257. package/lib/harness/output-style.d.ts +125 -0
  258. package/lib/harness/output-style.js +322 -0
  259. package/lib/harness/page-commands.d.ts +134 -0
  260. package/lib/harness/page-commands.js +1141 -0
  261. package/lib/harness/page-output.d.ts +67 -0
  262. package/lib/harness/page-output.js +139 -0
  263. package/lib/harness/page-watch.d.ts +171 -0
  264. package/lib/harness/page-watch.js +607 -0
  265. package/lib/harness/parse-check-node.d.ts +3 -0
  266. package/lib/harness/parse-check-node.js +132 -0
  267. package/lib/harness/path-args.d.ts +22 -0
  268. package/lib/harness/path-args.js +148 -0
  269. package/lib/harness/playwright-chromium.d.ts +16 -0
  270. package/lib/harness/playwright-chromium.js +86 -0
  271. package/lib/harness/prepare.d.ts +168 -0
  272. package/lib/harness/prepare.js +364 -0
  273. package/lib/harness/prompt-editor.d.ts +17 -0
  274. package/lib/harness/prompt-editor.js +354 -0
  275. package/lib/harness/prompt-history.d.ts +13 -0
  276. package/lib/harness/prompt-history.js +89 -0
  277. package/lib/harness/rebuild-advice.d.ts +6 -0
  278. package/lib/harness/rebuild-advice.js +39 -0
  279. package/lib/harness/run-log.d.ts +47 -0
  280. package/lib/harness/run-log.js +140 -0
  281. package/lib/harness/run-logs.d.ts +132 -0
  282. package/lib/harness/run-logs.js +241 -0
  283. package/lib/harness/run.d.ts +194 -0
  284. package/lib/harness/run.js +1973 -0
  285. package/lib/harness/runs.d.ts +229 -0
  286. package/lib/harness/runs.js +726 -0
  287. package/lib/harness/save-html.d.ts +39 -0
  288. package/lib/harness/save-html.js +89 -0
  289. package/lib/harness/saved-pages.d.ts +120 -0
  290. package/lib/harness/saved-pages.js +275 -0
  291. package/lib/harness/script-mark.d.ts +17 -0
  292. package/lib/harness/script-mark.js +56 -0
  293. package/lib/harness/snapshot.d.ts +143 -0
  294. package/lib/harness/snapshot.js +474 -0
  295. package/lib/harness/stuck-tabs.d.ts +19 -0
  296. package/lib/harness/stuck-tabs.js +131 -0
  297. package/lib/harness/tab-refs.d.ts +20 -0
  298. package/lib/harness/tab-refs.js +80 -0
  299. package/lib/harness/tampermonkey.d.ts +71 -0
  300. package/lib/harness/tampermonkey.js +356 -0
  301. package/lib/harness/tm-ids.d.ts +18 -0
  302. package/lib/harness/tm-ids.js +88 -0
  303. package/lib/harness/violentmonkey.d.ts +34 -0
  304. package/lib/harness/violentmonkey.js +162 -0
  305. package/lib/harness/wait.d.ts +77 -0
  306. package/lib/harness/wait.js +458 -0
  307. package/lib/http-read.d.ts +30 -0
  308. package/lib/http-read.js +142 -0
  309. package/lib/local-file-overrides.d.ts +35 -0
  310. package/lib/local-file-overrides.js +558 -0
  311. package/lib/manifest.json +38 -0
  312. package/lib/markup-response.d.ts +11 -0
  313. package/lib/markup-response.js +126 -0
  314. package/lib/match-targets.d.ts +18 -0
  315. package/lib/match-targets.js +305 -0
  316. package/lib/menu-captions.d.ts +1 -0
  317. package/lib/menu-captions.js +22 -0
  318. package/lib/parse-check-protocol.d.ts +27 -0
  319. package/lib/parse-check-protocol.js +51 -0
  320. package/lib/parse-location.d.ts +12 -0
  321. package/lib/parse-location.js +171 -0
  322. package/lib/phase-timing.d.ts +12 -0
  323. package/lib/phase-timing.js +155 -0
  324. package/lib/public-suffixes.d.ts +1 -0
  325. package/lib/public-suffixes.js +6957 -0
  326. package/lib/run-context.d.ts +2 -0
  327. package/lib/run-context.js +31 -0
  328. package/lib/runtime-messages.d.ts +10 -0
  329. package/lib/runtime-messages.js +34 -0
  330. package/lib/sandboxed-page.d.ts +5 -0
  331. package/lib/sandboxed-page.js +35 -0
  332. package/lib/script-build.d.ts +111 -0
  333. package/lib/script-build.js +787 -0
  334. package/lib/script-display.d.ts +51 -0
  335. package/lib/script-display.js +383 -0
  336. package/lib/script-icon.d.ts +16 -0
  337. package/lib/script-icon.js +43 -0
  338. package/lib/script-links.d.ts +24 -0
  339. package/lib/script-links.js +204 -0
  340. package/lib/script-source-url.d.ts +8 -0
  341. package/lib/script-source-url.js +214 -0
  342. package/lib/script-world.d.ts +6 -0
  343. package/lib/script-world.js +65 -0
  344. package/lib/sm-dev-protocol.d.ts +251 -0
  345. package/lib/sm-dev-protocol.js +84 -0
  346. package/lib/source-map.d.ts +32 -0
  347. package/lib/source-map.js +177 -0
  348. package/lib/stack-link.d.ts +15 -0
  349. package/lib/stack-link.js +138 -0
  350. package/lib/unsafe-window-use.d.ts +1 -0
  351. package/lib/unsafe-window-use.js +229 -0
  352. package/lib/url-match.d.ts +40 -0
  353. package/lib/url-match.js +734 -0
  354. package/lib/userscript-header.d.ts +33 -0
  355. package/lib/userscript-header.js +248 -0
  356. package/lib/version-compare.d.ts +6 -0
  357. package/lib/version-compare.js +141 -0
  358. package/lib/version-probe.d.ts +17 -0
  359. package/lib/version-probe.js +120 -0
  360. package/package.json +55 -3
  361. package/skills/SourceMonkey-dev/SKILL.md +868 -0
  362. package/skills/SourceMonkey-dev/references/cdp.md +293 -0
  363. package/skills/SourceMonkey-dev/references/commands.md +297 -0
  364. package/skills/SourceMonkey-dev/references/other-managers.md +63 -0
  365. package/skills/SourceMonkey-dev/references/specs.md +46 -0
  366. package/skills/SourceMonkey-friction/SKILL.md +103 -0
  367. package/skills/SourceMonkey-friction/references/template.md +59 -0
@@ -0,0 +1,308 @@
1
+ // The eval hook: one statement sm-dev's scripts get at the top of their
2
+ // user program, so `sm-dev eval --script` can run code inside a
3
+ // script's own scope and see what it sees: its `GM_*` bindings, its
4
+ // `@require`s' top-level declarations, and its own.
5
+ //
6
+ // ;(globalThis[<key>] || <new map>)[<script id>] =
7
+ // ({ 'sm-dev eval': (code) => eval(code) })['sm-dev eval'];
8
+ //
9
+ // - A direct `eval` runs in the scope it's written in, so the arrow is a
10
+ // handle on the user program's scope that outlives the script's run.
11
+ // - Only scripts in an sm-dev run's test collection get it, never the
12
+ // person's installed scripts: the handle reaches everything the
13
+ // script can, `GM_*` included, and a MAIN-world script's is on the
14
+ // page's `window`. Its scope includes `__smReg`, the world's registry
15
+ // (src/extension/channel.ts), so it reaches every page-world script's
16
+ // GM runtime there, not just its own.
17
+ // - The key names the run and the map isn't enumerable, so it stays out
18
+ // of a page's casual view. A page that looks for it can still find it.
19
+ // - It needs the script not to shadow `globalThis`, `Object` or `eval`
20
+ // where it sits.
21
+ // - A script whose code opens with an IIFE (immediately invoked
22
+ // function expression), the usual `(function () { ... })()` wrapper,
23
+ // gets a second copy just inside it. That one replaces the first in
24
+ // the map as the IIFE starts, and sees the IIFE's locals as well:
25
+ // an inner scope sees everything the outer one does.
26
+ //
27
+ // Each copy goes after its scope's directive prologue (`"use strict"`):
28
+ // a statement ahead of a directive turns it into a plain string, and
29
+ // the code would run sloppy. On the same line, so no line moves.
30
+ // The arrow's parameter, which the evaluated code sees too: named so no
31
+ // script's own would be shadowed by it.
32
+ const CODE_PARAM = '__smDevEvalCode';
33
+ // The arrow's name, which its stack frame shows. Assigned straight to
34
+ // the map, it has none, and V8 names the frame after the map key, the
35
+ // script's id. Made under an object literal key, it takes that key.
36
+ const FRAME_NAME = JSON.stringify('sm-dev eval');
37
+ /** The global key a run's eval hooks are kept under. */
38
+ export function evalHookKey(run) {
39
+ return `__smDevEval:${run}`;
40
+ }
41
+ /**
42
+ * `program` (requires + body, as composed) with the hook in it: at its
43
+ * top, and inside the script's IIFE when its own source, from
44
+ * `mainStart`, opens with one.
45
+ */
46
+ export function withEvalHook(program, key, scriptId, mainStart = 0) {
47
+ const k = JSON.stringify(key);
48
+ const hook = `;(globalThis[${k}]||Object.defineProperty(globalThis,${k},{value:{}})[${k}])[${JSON.stringify(scriptId)}]=({${FRAME_NAME}:(${CODE_PARAM})=>eval(${CODE_PARAM})})[${FRAME_NAME}];`;
49
+ const outer = directivePrologueEnd(program);
50
+ const body = leadingFunctionBody(program, directivePrologueEnd(program, mainStart));
51
+ if (body < 0)
52
+ return program.slice(0, outer) + hook + program.slice(outer);
53
+ const inner = directivePrologueEnd(program, body);
54
+ return program.slice(0, outer) + hook + program.slice(outer, inner) + hook + program.slice(inner);
55
+ }
56
+ /**
57
+ * Where the body of the function expression the code at `from` opens
58
+ * with starts, just past its `{`: the IIFE in `(function () {`,
59
+ * `(() => {`, `(async function () {`, `!function () {` and the like.
60
+ * -1 when it opens with anything else, an arrow with an expression
61
+ * body included.
62
+ *
63
+ * Whether the function is called isn't checked: a copy of the hook in
64
+ * one that never runs is never registered, and the outer one stays.
65
+ * Nor is whether it's the only statement: a first IIFE's scope sees
66
+ * what follows it at the top level too.
67
+ */
68
+ export function leadingFunctionBody(program, from) {
69
+ let i = skipSpace(program, from).at;
70
+ while (program[i] === ';')
71
+ i = skipSpace(program, i + 1).at;
72
+ if (/[!+\-~]/.test(program[i] ?? ''))
73
+ return functionBodyAt(program, skipSpace(program, i + 1).at, 0);
74
+ if (wordAt(program, i) === 'void')
75
+ return functionBodyAt(program, skipSpace(program, i + 4).at, 0);
76
+ // Without a prefix, only a parenthesis makes it an expression: a bare
77
+ // `function f() {` or `async function` is a declaration, a helper
78
+ // whose scope would shadow the script's names.
79
+ return program[i] === '(' ? functionBodyAt(program, i, 0) : -1;
80
+ }
81
+ // The body start of a function expression at `i`, through grouping
82
+ // parentheses, or -1.
83
+ function functionBodyAt(program, at, depth) {
84
+ let i = skipSpace(program, at).at;
85
+ if (wordAt(program, i) === 'async')
86
+ i = skipSpace(program, i + 5).at;
87
+ const word = wordAt(program, i);
88
+ if (word === 'function') {
89
+ i = skipSpace(program, i + 8).at;
90
+ if (program[i] === '*')
91
+ i = skipSpace(program, i + 1).at;
92
+ const name = wordAt(program, i);
93
+ if (name)
94
+ i = skipSpace(program, i + name.length).at;
95
+ if (program[i] !== '(')
96
+ return -1;
97
+ const close = matchingClose(program, i);
98
+ if (close < 0)
99
+ return -1;
100
+ i = skipSpace(program, close + 1).at;
101
+ return program[i] === '{' ? i + 1 : -1;
102
+ }
103
+ if (word)
104
+ return arrowBody(program, i + word.length);
105
+ if (program[i] !== '(')
106
+ return -1;
107
+ // A grouping parenthesis, looked into first, or an arrow's parameters.
108
+ if (depth < 4) {
109
+ const inner = functionBodyAt(program, i + 1, depth + 1);
110
+ if (inner >= 0)
111
+ return inner;
112
+ }
113
+ const close = matchingClose(program, i);
114
+ return close < 0 ? -1 : arrowBody(program, close + 1);
115
+ }
116
+ // The body start of an arrow whose parameters end at `at`, or -1.
117
+ function arrowBody(program, at) {
118
+ const arrow = skipSpace(program, at);
119
+ if (arrow.newline || !program.startsWith('=>', arrow.at))
120
+ return -1;
121
+ const brace = skipSpace(program, arrow.at + 2).at;
122
+ return program[brace] === '{' ? brace + 1 : -1;
123
+ }
124
+ // The identifier or keyword starting at `i`, or ''.
125
+ function wordAt(text, i) {
126
+ return /^[A-Za-z_$][\w$]*/.exec(text.slice(i, i + 64))?.[0] ?? '';
127
+ }
128
+ // The closer matching the bracket at `open`, past strings, template
129
+ // literals, comments and regular expressions, or -1 when the text runs
130
+ // out or reads as something unexpected.
131
+ function matchingClose(text, open) {
132
+ const closers = [];
133
+ // Whether a `/` here starts a regular expression rather than divides.
134
+ let regexAllowed = true;
135
+ for (let i = open; i < text.length; i++) {
136
+ const c = text[i];
137
+ if (c === '(' || c === '[' || c === '{') {
138
+ closers.push(c === '(' ? ')' : c === '[' ? ']' : '}');
139
+ regexAllowed = true;
140
+ }
141
+ else if (c === ')' || c === ']' || c === '}') {
142
+ if (closers.pop() !== c)
143
+ return -1;
144
+ if (closers.length === 0)
145
+ return i;
146
+ regexAllowed = false;
147
+ }
148
+ else if (c === '"' || c === '\'') {
149
+ i = stringEnd(text, i);
150
+ if (i < 0)
151
+ return -1;
152
+ regexAllowed = false;
153
+ }
154
+ else if (c === '`') {
155
+ i = templateEnd(text, i);
156
+ if (i < 0)
157
+ return -1;
158
+ regexAllowed = false;
159
+ }
160
+ else if (c === '/' && (text[i + 1] === '/' || text[i + 1] === '*')) {
161
+ i = skipSpace(text, i).at - 1;
162
+ }
163
+ else if (c === '/' && regexAllowed) {
164
+ i = regexEnd(text, i);
165
+ if (i < 0)
166
+ return -1;
167
+ regexAllowed = false;
168
+ }
169
+ else if (/[\w$]/.test(c)) {
170
+ const word = wordAt(text, i) || c;
171
+ // After a keyword like `return`, an expression starts.
172
+ regexAllowed = /^(return|typeof|case|do|else|in|instanceof|new|delete|void|throw|yield|await)$/.test(word);
173
+ i += word.length - 1;
174
+ }
175
+ else if (!/\s/.test(c)) {
176
+ regexAllowed = true;
177
+ }
178
+ }
179
+ return -1;
180
+ }
181
+ // The index of the quote closing the string at `i`, or -1.
182
+ function stringEnd(text, i) {
183
+ const quote = text[i];
184
+ for (let j = i + 1; j < text.length; j++) {
185
+ if (text[j] === '\\')
186
+ j++;
187
+ else if (text[j] === quote)
188
+ return j;
189
+ else if (text[j] === '\n')
190
+ return -1;
191
+ }
192
+ return -1;
193
+ }
194
+ // The index of the backtick closing the template literal at `i`, its
195
+ // `${...}` parts skipped, or -1.
196
+ function templateEnd(text, i) {
197
+ for (let j = i + 1; j < text.length; j++) {
198
+ if (text[j] === '\\')
199
+ j++;
200
+ else if (text[j] === '`')
201
+ return j;
202
+ else if (text[j] === '$' && text[j + 1] === '{') {
203
+ j = matchingClose(text, j + 1);
204
+ if (j < 0)
205
+ return -1;
206
+ }
207
+ }
208
+ return -1;
209
+ }
210
+ // The index of the `/` closing the regular expression at `i`, or -1.
211
+ function regexEnd(text, i) {
212
+ let inClass = false;
213
+ for (let j = i + 1; j < text.length; j++) {
214
+ const c = text[j];
215
+ if (c === '\\')
216
+ j++;
217
+ else if (c === '\n' || c === '\r')
218
+ return -1;
219
+ else if (c === '[')
220
+ inClass = true;
221
+ else if (c === ']')
222
+ inClass = false;
223
+ else if (c === '/' && !inClass)
224
+ return j;
225
+ }
226
+ return -1;
227
+ }
228
+ /**
229
+ * Where the directive prologue of the code at `from` ends (a program,
230
+ * or a function body): just past its last directive (a string literal
231
+ * statement at the start, `"use strict"` the one that matters), or
232
+ * `from` when it has none. Comments and whitespace before and between
233
+ * directives are skipped.
234
+ *
235
+ * A string that may be the start of a longer expression isn't counted
236
+ * as a directive: then the hook goes before it, which is right unless
237
+ * the guess was wrong, in code no one writes (`'use strict'` followed
238
+ * on the next line by `in x`).
239
+ */
240
+ export function directivePrologueEnd(program, from = 0) {
241
+ let end = from;
242
+ let i = skipSpace(program, from).at;
243
+ for (;;) {
244
+ const quote = program[i];
245
+ if (quote !== '"' && quote !== '\'')
246
+ return end;
247
+ // The literal's end. Unclosed, or broken by a line break: not ours
248
+ // to judge, so no further.
249
+ let j = i + 1;
250
+ while (j < program.length && program[j] !== quote) {
251
+ if (program[j] === '\n' || program[j] === '\r')
252
+ return end;
253
+ j += program[j] === '\\' ? 2 : 1;
254
+ }
255
+ if (j >= program.length)
256
+ return end;
257
+ const literalEnd = j + 1;
258
+ const after = skipSpace(program, literalEnd);
259
+ const next = program[after.at];
260
+ if (next === ';') {
261
+ end = after.at + 1;
262
+ }
263
+ else if (next === undefined || next === '}' || (after.newline && !continuesExpression(program, after.at))) {
264
+ // Ended by the line break (automatic semicolon insertion), by the
265
+ // end of the program, or by the end of a function body.
266
+ end = literalEnd;
267
+ }
268
+ else {
269
+ return end;
270
+ }
271
+ i = skipSpace(program, end).at;
272
+ }
273
+ }
274
+ // Past whitespace and comments from `at`, and whether a line break was
275
+ // among them (a `/* */` comment's included).
276
+ function skipSpace(text, at) {
277
+ let newline = false;
278
+ let i = at;
279
+ for (;;) {
280
+ const c = text[i];
281
+ if (c === '\n' || c === '\r' || c === '\u2028' || c === '\u2029') {
282
+ newline = true;
283
+ i++;
284
+ }
285
+ else if (c !== undefined && /\s/.test(c)) {
286
+ i++;
287
+ }
288
+ else if (c === '/' && text[i + 1] === '/') {
289
+ while (i < text.length && text[i] !== '\n' && text[i] !== '\r')
290
+ i++;
291
+ }
292
+ else if (c === '/' && text[i + 1] === '*') {
293
+ const close = text.indexOf('*/', i + 2);
294
+ const stop = close < 0 ? text.length : close + 2;
295
+ if (/[\n\r\u2028\u2029]/.test(text.slice(i, stop)))
296
+ newline = true;
297
+ i = stop;
298
+ }
299
+ else {
300
+ return { at: i, newline };
301
+ }
302
+ }
303
+ }
304
+ // Whether the token at `at` could carry on an expression from the line
305
+ // before, so no semicolon is inserted between them.
306
+ function continuesExpression(text, at) {
307
+ return /[[(.,?+\-*/%=<>&|^`]/.test(text[at]) || /^(in|instanceof)\b/.test(text.slice(at, at + 11));
308
+ }