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.
- package/LICENSE +21 -0
- package/README.md +87 -2
- package/dist/bytes.js +37 -0
- package/dist/channel-placeholder.js +5 -0
- package/dist/collection-scan.js +17 -0
- package/dist/collections.html +353 -0
- package/dist/compare.html +358 -0
- package/dist/composed-source.js +205 -0
- package/dist/connect-prompt.html +47 -0
- package/dist/debug/icons.html +211 -0
- package/dist/debug/storage.html +163 -0
- package/dist/debug-log.js +75 -0
- package/dist/diagnostic-location.js +64 -0
- package/dist/eval-hook.js +308 -0
- package/dist/extension/background.js +5263 -0
- package/dist/extension/channel.js +133 -0
- package/dist/extension/code-links.js +187 -0
- package/dist/extension/code-tabs.js +460 -0
- package/dist/extension/collection-dialog.js +619 -0
- package/dist/extension/collection-display.js +322 -0
- package/dist/extension/collections.js +2905 -0
- package/dist/extension/compare.js +867 -0
- package/dist/extension/concurrency.js +186 -0
- package/dist/extension/connect-grants.js +109 -0
- package/dist/extension/connect-prompt-page.js +70 -0
- package/dist/extension/connect-prompt.js +266 -0
- package/dist/extension/copy-button.js +63 -0
- package/dist/extension/copy-dialog.js +502 -0
- package/dist/extension/copy-preference.js +66 -0
- package/dist/extension/debug/icons.js +203 -0
- package/dist/extension/debug/storage.js +365 -0
- package/dist/extension/deep-link.js +77 -0
- package/dist/extension/delete-dialog.js +432 -0
- package/dist/extension/delete-icon.js +40 -0
- package/dist/extension/details-tooltips.js +66 -0
- package/dist/extension/directories.js +679 -0
- package/dist/extension/export-backup.js +407 -0
- package/dist/extension/export-dialog.js +142 -0
- package/dist/extension/file-access.js +74 -0
- package/dist/extension/file-changes.js +346 -0
- package/dist/extension/frame-info.js +85 -0
- package/dist/extension/github-provider.js +336 -0
- package/dist/extension/glyph.js +84 -0
- package/dist/extension/gm-bindings.js +601 -0
- package/dist/extension/gm-download.js +419 -0
- package/dist/extension/gm-menu.js +228 -0
- package/dist/extension/gm-notification.js +141 -0
- package/dist/extension/gm-originator-map.js +23 -0
- package/dist/extension/gm-tab-data.js +121 -0
- package/dist/extension/gm-tab.js +160 -0
- package/dist/extension/gm-url-change.js +111 -0
- package/dist/extension/gm-url-scheme.js +27 -0
- package/dist/extension/gm-values.js +176 -0
- package/dist/extension/gm-window-control.js +104 -0
- package/dist/extension/gm-xhr-headers.js +333 -0
- package/dist/extension/gm-xhr.js +584 -0
- package/dist/extension/injector.js +3145 -0
- package/dist/extension/install-capture.js +277 -0
- package/dist/extension/line-diff.js +233 -0
- package/dist/extension/local-copy.js +560 -0
- package/dist/extension/local-delete.js +276 -0
- package/dist/extension/location-kinds.js +108 -0
- package/dist/extension/log-format.js +158 -0
- package/dist/extension/managed-changes.js +361 -0
- package/dist/extension/managed-items.js +57 -0
- package/dist/extension/match-index.js +375 -0
- package/dist/extension/missing-scripts.js +66 -0
- package/dist/extension/more-menu.js +109 -0
- package/dist/extension/move-dialog.js +197 -0
- package/dist/extension/offscreen.js +37 -0
- package/dist/extension/options.js +504 -0
- package/dist/extension/page-heading.js +170 -0
- package/dist/extension/page-links.js +199 -0
- package/dist/extension/parse-check-client.js +70 -0
- package/dist/extension/parse-check.js +161 -0
- package/dist/extension/parse-sandbox-host.js +172 -0
- package/dist/extension/parse-sandbox.js +175 -0
- package/dist/extension/popup-commands-open.js +41 -0
- package/dist/extension/popup-view.js +387 -0
- package/dist/extension/popup.js +703 -0
- package/dist/extension/prism-userscript.js +53 -0
- package/dist/extension/refresh-error.js +136 -0
- package/dist/extension/refresh-targets.js +160 -0
- package/dist/extension/related-versions.js +1144 -0
- package/dist/extension/resize-observer-loop.js +19 -0
- package/dist/extension/row-cache.js +387 -0
- package/dist/extension/script-blobs.js +413 -0
- package/dist/extension/script-details.js +658 -0
- package/dist/extension/script-enablement.js +285 -0
- package/dist/extension/script-identity.js +310 -0
- package/dist/extension/script-keys.js +54 -0
- package/dist/extension/script-log-id.js +155 -0
- package/dist/extension/script-log.js +290 -0
- package/dist/extension/script-rejection.js +104 -0
- package/dist/extension/script-sites.js +158 -0
- package/dist/extension/script-store.js +3507 -0
- package/dist/extension/script-updater.js +991 -0
- package/dist/extension/script-url-hash.js +61 -0
- package/dist/extension/select-all.js +37 -0
- package/dist/extension/select-open-guard.js +90 -0
- package/dist/extension/site-icon.js +1261 -0
- package/dist/extension/sm-dev-link.js +302 -0
- package/dist/extension/solo-click.js +58 -0
- package/dist/extension/sticky-numbers.js +188 -0
- package/dist/extension/storage-breakdown.js +253 -0
- package/dist/extension/storage-scan.js +86 -0
- package/dist/extension/storage-usage.js +194 -0
- package/dist/extension/structural-keys.js +29 -0
- package/dist/extension/sw-teardown.js +36 -0
- package/dist/extension/tab-status.js +403 -0
- package/dist/extension/toolbar-summary.js +105 -0
- package/dist/extension/user-scripts-access.js +43 -0
- package/dist/extension/userscript.js +3672 -0
- package/dist/extension/value-store.js +204 -0
- package/dist/extension/version-probe-fetch.js +68 -0
- package/dist/extension/worker-client.js +109 -0
- package/dist/extension/worker-ops.js +171 -0
- package/dist/extension/zip-writer.js +24 -0
- package/dist/external-files.js +878 -0
- package/dist/file-loader.js +436 -0
- package/dist/file-locations.js +439 -0
- package/dist/generated-wrappers.js +5 -0
- package/dist/github-auth.js +148 -0
- package/dist/github-urls.js +46 -0
- package/dist/gm-api-catalog.js +217 -0
- package/dist/gm-connect.js +273 -0
- package/dist/gm-xhr-types.js +5 -0
- package/dist/http-read.js +142 -0
- package/dist/icons/icon-128.png +0 -0
- package/dist/icons/icon-16.png +0 -0
- package/dist/icons/icon-48.png +0 -0
- package/dist/local-file-overrides.js +558 -0
- package/dist/manifest.json +38 -0
- package/dist/markup-response.js +126 -0
- package/dist/match-targets.js +305 -0
- package/dist/menu-captions.js +22 -0
- package/dist/offscreen.html +39 -0
- package/dist/options.html +197 -0
- package/dist/parse-check-protocol.js +51 -0
- package/dist/parse-location.js +171 -0
- package/dist/parse-sandbox.html +56 -0
- package/dist/phase-timing.js +155 -0
- package/dist/popup.html +197 -0
- package/dist/public-suffixes.js +6957 -0
- package/dist/run-context.js +31 -0
- package/dist/runtime-messages.js +34 -0
- package/dist/sandboxed-page.js +35 -0
- package/dist/script-build.js +787 -0
- package/dist/script-display.js +383 -0
- package/dist/script-icon.js +43 -0
- package/dist/script-links.js +204 -0
- package/dist/script-source-url.js +214 -0
- package/dist/script-world.js +65 -0
- package/dist/sm-dev-protocol.js +84 -0
- package/dist/source-map.js +177 -0
- package/dist/stack-link.js +138 -0
- package/dist/styles.css +825 -0
- package/dist/unsafe-window-use.js +229 -0
- package/dist/url-match.js +734 -0
- package/dist/userscript-header.js +248 -0
- package/dist/userscript.html +1165 -0
- package/dist/vendor/fflate.LICENSE +21 -0
- package/dist/vendor/fflate.js +2692 -0
- package/dist/vendor/prism/prism-line-numbers.css +1 -0
- package/dist/vendor/prism/prism-line-numbers.js +1 -0
- package/dist/vendor/prism/prism.css +1 -0
- package/dist/vendor/prism/prism.js +1946 -0
- package/dist/version-compare.js +141 -0
- package/dist/version-probe.js +120 -0
- package/lib/build-info.json +1 -0
- package/lib/bytes.d.ts +3 -0
- package/lib/bytes.js +37 -0
- package/lib/channel-placeholder.d.ts +1 -0
- package/lib/channel-placeholder.js +5 -0
- package/lib/collection-scan.d.ts +8 -0
- package/lib/collection-scan.js +17 -0
- package/lib/composed-source.d.ts +28 -0
- package/lib/composed-source.js +205 -0
- package/lib/debug-log.d.ts +9 -0
- package/lib/debug-log.js +75 -0
- package/lib/diagnostic-location.d.ts +8 -0
- package/lib/diagnostic-location.js +64 -0
- package/lib/eval-hook.d.ts +34 -0
- package/lib/eval-hook.js +308 -0
- package/lib/external-files.d.ts +111 -0
- package/lib/external-files.js +878 -0
- package/lib/file-loader.d.ts +48 -0
- package/lib/file-loader.js +436 -0
- package/lib/file-locations.d.ts +44 -0
- package/lib/file-locations.js +439 -0
- package/lib/generated-wrappers.d.ts +11 -0
- package/lib/generated-wrappers.js +5 -0
- package/lib/github-auth.d.ts +12 -0
- package/lib/github-auth.js +148 -0
- package/lib/github-urls.d.ts +1 -0
- package/lib/github-urls.js +46 -0
- package/lib/gm-api-catalog.d.ts +24 -0
- package/lib/gm-api-catalog.js +217 -0
- package/lib/gm-connect.d.ts +34 -0
- package/lib/gm-connect.js +273 -0
- package/lib/gm-xhr-types.d.ts +68 -0
- package/lib/gm-xhr-types.js +5 -0
- package/lib/harness/browser-extensions.d.ts +73 -0
- package/lib/harness/browser-extensions.js +285 -0
- package/lib/harness/browser-lang.d.ts +20 -0
- package/lib/harness/browser-lang.js +86 -0
- package/lib/harness/browser-launch.d.ts +14 -0
- package/lib/harness/browser-launch.js +184 -0
- package/lib/harness/checks.d.ts +110 -0
- package/lib/harness/checks.js +321 -0
- package/lib/harness/cli.d.ts +2 -0
- package/lib/harness/cli.js +2259 -0
- package/lib/harness/command-args.d.ts +91 -0
- package/lib/harness/command-args.js +369 -0
- package/lib/harness/command-lines.d.ts +80 -0
- package/lib/harness/command-lines.js +180 -0
- package/lib/harness/command-list.d.ts +206 -0
- package/lib/harness/command-list.js +1475 -0
- package/lib/harness/console-commands.d.ts +463 -0
- package/lib/harness/console-commands.js +3216 -0
- package/lib/harness/download-watch.d.ts +21 -0
- package/lib/harness/download-watch.js +156 -0
- package/lib/harness/extension-backend.d.ts +41 -0
- package/lib/harness/extension-backend.js +100 -0
- package/lib/harness/extension-host.d.ts +112 -0
- package/lib/harness/extension-host.js +552 -0
- package/lib/harness/extension-launch.d.ts +67 -0
- package/lib/harness/extension-launch.js +285 -0
- package/lib/harness/extension-link.d.ts +315 -0
- package/lib/harness/extension-link.js +607 -0
- package/lib/harness/external-manager.d.ts +146 -0
- package/lib/harness/external-manager.js +414 -0
- package/lib/harness/fixture.d.ts +165 -0
- package/lib/harness/fixture.js +461 -0
- package/lib/harness/frame-sessions.d.ts +71 -0
- package/lib/harness/frame-sessions.js +248 -0
- package/lib/harness/frames.d.ts +68 -0
- package/lib/harness/frames.js +216 -0
- package/lib/harness/help-format.d.ts +17 -0
- package/lib/harness/help-format.js +127 -0
- package/lib/harness/host.d.ts +352 -0
- package/lib/harness/host.js +423 -0
- package/lib/harness/index.d.ts +8 -0
- package/lib/harness/index.js +10 -0
- package/lib/harness/input-file.d.ts +18 -0
- package/lib/harness/input-file.js +61 -0
- package/lib/harness/json-output.d.ts +565 -0
- package/lib/harness/json-output.js +71 -0
- package/lib/harness/manager-actions.d.ts +21 -0
- package/lib/harness/manager-actions.js +129 -0
- package/lib/harness/manager-commands.d.ts +142 -0
- package/lib/harness/manager-commands.js +1196 -0
- package/lib/harness/manager-fetch.d.ts +33 -0
- package/lib/harness/manager-fetch.js +239 -0
- package/lib/harness/managers.d.ts +24 -0
- package/lib/harness/managers.js +27 -0
- package/lib/harness/output-style.d.ts +125 -0
- package/lib/harness/output-style.js +322 -0
- package/lib/harness/page-commands.d.ts +134 -0
- package/lib/harness/page-commands.js +1141 -0
- package/lib/harness/page-output.d.ts +67 -0
- package/lib/harness/page-output.js +139 -0
- package/lib/harness/page-watch.d.ts +171 -0
- package/lib/harness/page-watch.js +607 -0
- package/lib/harness/parse-check-node.d.ts +3 -0
- package/lib/harness/parse-check-node.js +132 -0
- package/lib/harness/path-args.d.ts +22 -0
- package/lib/harness/path-args.js +148 -0
- package/lib/harness/playwright-chromium.d.ts +16 -0
- package/lib/harness/playwright-chromium.js +86 -0
- package/lib/harness/prepare.d.ts +168 -0
- package/lib/harness/prepare.js +364 -0
- package/lib/harness/prompt-editor.d.ts +17 -0
- package/lib/harness/prompt-editor.js +354 -0
- package/lib/harness/prompt-history.d.ts +13 -0
- package/lib/harness/prompt-history.js +89 -0
- package/lib/harness/rebuild-advice.d.ts +6 -0
- package/lib/harness/rebuild-advice.js +39 -0
- package/lib/harness/run-log.d.ts +47 -0
- package/lib/harness/run-log.js +140 -0
- package/lib/harness/run-logs.d.ts +132 -0
- package/lib/harness/run-logs.js +241 -0
- package/lib/harness/run.d.ts +194 -0
- package/lib/harness/run.js +1973 -0
- package/lib/harness/runs.d.ts +229 -0
- package/lib/harness/runs.js +726 -0
- package/lib/harness/save-html.d.ts +39 -0
- package/lib/harness/save-html.js +89 -0
- package/lib/harness/saved-pages.d.ts +120 -0
- package/lib/harness/saved-pages.js +275 -0
- package/lib/harness/script-mark.d.ts +17 -0
- package/lib/harness/script-mark.js +56 -0
- package/lib/harness/snapshot.d.ts +143 -0
- package/lib/harness/snapshot.js +474 -0
- package/lib/harness/stuck-tabs.d.ts +19 -0
- package/lib/harness/stuck-tabs.js +131 -0
- package/lib/harness/tab-refs.d.ts +20 -0
- package/lib/harness/tab-refs.js +80 -0
- package/lib/harness/tampermonkey.d.ts +71 -0
- package/lib/harness/tampermonkey.js +356 -0
- package/lib/harness/tm-ids.d.ts +18 -0
- package/lib/harness/tm-ids.js +88 -0
- package/lib/harness/violentmonkey.d.ts +34 -0
- package/lib/harness/violentmonkey.js +162 -0
- package/lib/harness/wait.d.ts +77 -0
- package/lib/harness/wait.js +458 -0
- package/lib/http-read.d.ts +30 -0
- package/lib/http-read.js +142 -0
- package/lib/local-file-overrides.d.ts +35 -0
- package/lib/local-file-overrides.js +558 -0
- package/lib/manifest.json +38 -0
- package/lib/markup-response.d.ts +11 -0
- package/lib/markup-response.js +126 -0
- package/lib/match-targets.d.ts +18 -0
- package/lib/match-targets.js +305 -0
- package/lib/menu-captions.d.ts +1 -0
- package/lib/menu-captions.js +22 -0
- package/lib/parse-check-protocol.d.ts +27 -0
- package/lib/parse-check-protocol.js +51 -0
- package/lib/parse-location.d.ts +12 -0
- package/lib/parse-location.js +171 -0
- package/lib/phase-timing.d.ts +12 -0
- package/lib/phase-timing.js +155 -0
- package/lib/public-suffixes.d.ts +1 -0
- package/lib/public-suffixes.js +6957 -0
- package/lib/run-context.d.ts +2 -0
- package/lib/run-context.js +31 -0
- package/lib/runtime-messages.d.ts +10 -0
- package/lib/runtime-messages.js +34 -0
- package/lib/sandboxed-page.d.ts +5 -0
- package/lib/sandboxed-page.js +35 -0
- package/lib/script-build.d.ts +111 -0
- package/lib/script-build.js +787 -0
- package/lib/script-display.d.ts +51 -0
- package/lib/script-display.js +383 -0
- package/lib/script-icon.d.ts +16 -0
- package/lib/script-icon.js +43 -0
- package/lib/script-links.d.ts +24 -0
- package/lib/script-links.js +204 -0
- package/lib/script-source-url.d.ts +8 -0
- package/lib/script-source-url.js +214 -0
- package/lib/script-world.d.ts +6 -0
- package/lib/script-world.js +65 -0
- package/lib/sm-dev-protocol.d.ts +251 -0
- package/lib/sm-dev-protocol.js +84 -0
- package/lib/source-map.d.ts +32 -0
- package/lib/source-map.js +177 -0
- package/lib/stack-link.d.ts +15 -0
- package/lib/stack-link.js +138 -0
- package/lib/unsafe-window-use.d.ts +1 -0
- package/lib/unsafe-window-use.js +229 -0
- package/lib/url-match.d.ts +40 -0
- package/lib/url-match.js +734 -0
- package/lib/userscript-header.d.ts +33 -0
- package/lib/userscript-header.js +248 -0
- package/lib/version-compare.d.ts +6 -0
- package/lib/version-compare.js +141 -0
- package/lib/version-probe.d.ts +17 -0
- package/lib/version-probe.js +120 -0
- package/package.json +55 -3
- package/skills/SourceMonkey-dev/SKILL.md +868 -0
- package/skills/SourceMonkey-dev/references/cdp.md +293 -0
- package/skills/SourceMonkey-dev/references/commands.md +297 -0
- package/skills/SourceMonkey-dev/references/other-managers.md +63 -0
- package/skills/SourceMonkey-dev/references/specs.md +46 -0
- package/skills/SourceMonkey-friction/SKILL.md +103 -0
- package/skills/SourceMonkey-friction/references/template.md +59 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// Node counterpart of `src/extension/parse-sandbox.ts` — the compile-only parse
|
|
2
|
+
// check, run under Node's V8 instead of Chrome's. Used by the development
|
|
3
|
+
// harness (`prepare.ts`), which runs the install pipeline outside a
|
|
4
|
+
// browser for `sm-dev` and the corpus validator.
|
|
5
|
+
//
|
|
6
|
+
// The extension can only do this inside a sandboxed extension page,
|
|
7
|
+
// because MV3's CSP forbids `eval` everywhere else and the location
|
|
8
|
+
// probes need to insert a `<script>`. Node has neither restriction, so
|
|
9
|
+
// the same two-step check (verdict, then location) is a few lines here:
|
|
10
|
+
//
|
|
11
|
+
// - the verdict comes from `new Function(src)`, byte-for-byte the
|
|
12
|
+
// call the sandbox makes;
|
|
13
|
+
// - the location comes from compiling the same text twice more with
|
|
14
|
+
// `new vm.Script`, which is Node's classic-script compile — the
|
|
15
|
+
// same thing appending a `<script>` element does in the sandbox.
|
|
16
|
+
//
|
|
17
|
+
// Everything downstream (`selectParseLocation`, `attachParseLocation`)
|
|
18
|
+
// is the extension's own code, so the probe selection rule is shared
|
|
19
|
+
// rather than reimplemented.
|
|
20
|
+
//
|
|
21
|
+
// Caveat worth remembering when reading results: Node's V8 is not
|
|
22
|
+
// Chrome's V8. Both accept the same language, but a very new syntax
|
|
23
|
+
// feature (or a wording change in a `SyntaxError` message) can differ
|
|
24
|
+
// between the two versions. `node --version` pins which one answered.
|
|
25
|
+
import vm from 'node:vm';
|
|
26
|
+
// Mirrors `parse-sandbox.ts` exactly, because the probe text is what
|
|
27
|
+
// the reported positions are relative to: change the framing and the
|
|
28
|
+
// line numbers stop matching the browser's.
|
|
29
|
+
//
|
|
30
|
+
// In the sandbox the sentinel is load-bearing for safety — appending a
|
|
31
|
+
// `<script>` element runs it, and only a guaranteed parse failure stops
|
|
32
|
+
// that. `new vm.Script` compiles without running either way, so here
|
|
33
|
+
// the sentinel is purely about parity. Keeping it means a source that
|
|
34
|
+
// ends mid-construct fails at the same place in both, which is the case
|
|
35
|
+
// `selectParseLocation`'s range check is reading.
|
|
36
|
+
const PROBE_SENTINEL = '\n(';
|
|
37
|
+
const WRAPPER_HEAD = 'function __smParseProbe__() {\n';
|
|
38
|
+
const WRAPPER_TAIL = '\n}';
|
|
39
|
+
// Any name works; it only has to be recognizable in the stack trace we
|
|
40
|
+
// parse the position out of. The `:` is the separator V8 puts before
|
|
41
|
+
// the line number — matched as a literal prefix rather than
|
|
42
|
+
// interpolated into a regex, so a future rename can't turn a character
|
|
43
|
+
// of the name into a wildcard.
|
|
44
|
+
const PROBE_FILENAME = 'sm-parse-probe.js';
|
|
45
|
+
const PROBE_HEAD_PREFIX = `${PROBE_FILENAME}:`;
|
|
46
|
+
/** The verdict, with probes attached when it's a syntax error. */
|
|
47
|
+
export function checkParseNode(source) {
|
|
48
|
+
try {
|
|
49
|
+
// eslint-disable-next-line no-new-func
|
|
50
|
+
new Function(source);
|
|
51
|
+
return { status: 'ok' };
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
55
|
+
// Only a SyntaxError means "this source is broken". A RangeError
|
|
56
|
+
// (parser stack overflow on pathologically nested source) means we
|
|
57
|
+
// couldn't tell — see the long note in parse-sandbox.ts.
|
|
58
|
+
if (!(err instanceof SyntaxError))
|
|
59
|
+
return { status: 'unknown', message };
|
|
60
|
+
return { status: 'syntax-error', message, probes: locate(source) };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function locate(source) {
|
|
64
|
+
try {
|
|
65
|
+
return {
|
|
66
|
+
wrapped: runProbe(`${WRAPPER_HEAD}${source}${WRAPPER_TAIL}${PROBE_SENTINEL}`, 1),
|
|
67
|
+
raw: runProbe(`${source}${PROBE_SENTINEL}`, 0),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Locating is a nicety; the verdict is the product.
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Compile `text` as a classic script and report where it failed.
|
|
76
|
+
// `lineOffset` is how many lines of our own framing precede the source,
|
|
77
|
+
// so the caller gets source coordinates back.
|
|
78
|
+
function runProbe(text, lineOffset) {
|
|
79
|
+
try {
|
|
80
|
+
new vm.Script(text, { filename: PROBE_FILENAME });
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
if (!(err instanceof SyntaxError))
|
|
84
|
+
return undefined;
|
|
85
|
+
const at = positionFromStack(err);
|
|
86
|
+
if (!at)
|
|
87
|
+
return undefined;
|
|
88
|
+
return { message: err.message, line: at.line - lineOffset, column: at.column };
|
|
89
|
+
}
|
|
90
|
+
// No error at all means the sentinel failed to do its job — and the
|
|
91
|
+
// source ran. Report no position; `selectParseLocation` then has one
|
|
92
|
+
// fewer probe to choose from.
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
// A `vm.Script` SyntaxError carries its position only in the rendered
|
|
96
|
+
// preamble at the top of `err.stack`, which V8 formats as:
|
|
97
|
+
//
|
|
98
|
+
// sm-parse-probe.js:3
|
|
99
|
+
// }
|
|
100
|
+
// ^
|
|
101
|
+
// (blank)
|
|
102
|
+
// SyntaxError: Unexpected token '}'
|
|
103
|
+
// at new Script (node:vm:…)
|
|
104
|
+
//
|
|
105
|
+
// The first line gives the 1-based line; the caret line gives the
|
|
106
|
+
// 1-based column as its first `^`. A stack whose first line isn't the
|
|
107
|
+
// preamble is one we don't recognize, and gets no position at all.
|
|
108
|
+
//
|
|
109
|
+
// **The column is best-effort; the line is not.** V8 clips the rendered
|
|
110
|
+
// frame at ~1020 characters, so for a longer source line the caret line
|
|
111
|
+
// is all spaces with no `^` in it and the true column is simply not in
|
|
112
|
+
// the stack. That is not exotic input here — a minified script, or a
|
|
113
|
+
// minified `@require`, is one enormous line, and bulk-checking real
|
|
114
|
+
// corpora is what this tool is for. Chrome's path reads `event.colno`
|
|
115
|
+
// and has the real column in every case, so this is the one place the
|
|
116
|
+
// Node port is knowingly less precise. We keep the line (exact, and the
|
|
117
|
+
// part that names a file) and fall back to column 1, which
|
|
118
|
+
// `COLUMN_UNKNOWN` marks as a fallback rather than a measurement.
|
|
119
|
+
// Nothing downstream depends on it: `selectParseLocation` compares only
|
|
120
|
+
// lines, so probe choice and the verdict are unaffected.
|
|
121
|
+
const COLUMN_UNKNOWN = 1;
|
|
122
|
+
function positionFromStack(err) {
|
|
123
|
+
const lines = String(err.stack ?? '').split('\n');
|
|
124
|
+
const head = lines[0] ?? '';
|
|
125
|
+
if (!head.startsWith(PROBE_HEAD_PREFIX))
|
|
126
|
+
return null;
|
|
127
|
+
const line = Number(head.slice(PROBE_HEAD_PREFIX.length));
|
|
128
|
+
if (!Number.isInteger(line))
|
|
129
|
+
return null;
|
|
130
|
+
const caretIndex = (lines[2] ?? '').indexOf('^');
|
|
131
|
+
return { line, column: caretIndex >= 0 ? caretIndex + 1 : COLUMN_UNKNOWN };
|
|
132
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const HAS_SCHEME: RegExp;
|
|
2
|
+
/**
|
|
3
|
+
* Whether a word is a glob: one with a `*` and no `scheme:` in front.
|
|
4
|
+
* A URL to open always has a scheme or a host with a dot, and no web
|
|
5
|
+
* page is at a `*`, so `example.com/*` is a glob too (and an error if
|
|
6
|
+
* it matches no file).
|
|
7
|
+
*/
|
|
8
|
+
export declare function isGlob(word: string): boolean;
|
|
9
|
+
export declare function isDirectory(file: string): boolean;
|
|
10
|
+
/** The `*.user.js` files under `dir`, as paths starting with `spelled`. */
|
|
11
|
+
export declare function walkScripts(dir: string, spelled: string, out: string[]): void;
|
|
12
|
+
/**
|
|
13
|
+
* What is wrong with a glob, or null. `**` only works as a whole path
|
|
14
|
+
* part (not `a**` or `**.user.js`), and not as the last one, which
|
|
15
|
+
* would leave the file name unmatched.
|
|
16
|
+
*/
|
|
17
|
+
export declare function globMistake(pattern: string): string | null;
|
|
18
|
+
/**
|
|
19
|
+
* The files a glob matches, sorted within each directory, no
|
|
20
|
+
* directories. The glob must have no globMistake.
|
|
21
|
+
*/
|
|
22
|
+
export declare function globFiles(pattern: string, cwd?: string): string[];
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// Globs and directory searches over the file system, for sm-dev's file
|
|
2
|
+
// arguments (see expandPathArg in checks.ts). `*` matches within one
|
|
3
|
+
// path segment, and a `**` segment matches any number of directories.
|
|
4
|
+
//
|
|
5
|
+
// Synchronous, so the command line can sort its words into scripts and
|
|
6
|
+
// URLs before deciding whether a command goes to a run.
|
|
7
|
+
import { readdirSync, statSync } from 'node:fs';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { quoted } from './output-style.js';
|
|
10
|
+
const SCRIPT_FILE = /\.user\.js$/i;
|
|
11
|
+
// Words with a scheme are URLs, whatever they contain. Two letters or
|
|
12
|
+
// more, so a Windows drive (`C:`) stays a path.
|
|
13
|
+
export const HAS_SCHEME = /^[a-z][a-z0-9+.-]+:/i;
|
|
14
|
+
// Path separators: a backslash only where it is one.
|
|
15
|
+
const SEPARATORS = path.sep === '\\' ? /[/\\]+/ : /\/+/;
|
|
16
|
+
/**
|
|
17
|
+
* Whether a word is a glob: one with a `*` and no `scheme:` in front.
|
|
18
|
+
* A URL to open always has a scheme or a host with a dot, and no web
|
|
19
|
+
* page is at a `*`, so `example.com/*` is a glob too (and an error if
|
|
20
|
+
* it matches no file).
|
|
21
|
+
*/
|
|
22
|
+
export function isGlob(word) {
|
|
23
|
+
return word.includes('*') && !HAS_SCHEME.test(word);
|
|
24
|
+
}
|
|
25
|
+
export function isDirectory(file) {
|
|
26
|
+
try {
|
|
27
|
+
return statSync(file).isDirectory();
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function entriesOf(dir) {
|
|
34
|
+
try {
|
|
35
|
+
return readdirSync(dir, { withFileTypes: true }).sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// A directory searched in full, or by `**`: not node_modules, nor
|
|
42
|
+
// hidden ones, which hold copies and tool state rather than sources.
|
|
43
|
+
// Symbolic links to directories aren't followed either, so a link
|
|
44
|
+
// back up the tree can't loop.
|
|
45
|
+
const skipped = (entry) => entry.name === 'node_modules' || entry.name.startsWith('.');
|
|
46
|
+
/** The `*.user.js` files under `dir`, as paths starting with `spelled`. */
|
|
47
|
+
export function walkScripts(dir, spelled, out) {
|
|
48
|
+
for (const entry of entriesOf(dir)) {
|
|
49
|
+
if (skipped(entry))
|
|
50
|
+
continue;
|
|
51
|
+
const full = path.join(dir, entry.name);
|
|
52
|
+
const shown = path.join(spelled, entry.name);
|
|
53
|
+
if (entry.isDirectory())
|
|
54
|
+
walkScripts(full, shown, out);
|
|
55
|
+
else if (SCRIPT_FILE.test(entry.name))
|
|
56
|
+
out.push(shown);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// One path segment's pattern: `*` is any run of characters but `/`.
|
|
60
|
+
function segmentRegExp(segment) {
|
|
61
|
+
const body = segment.split('*').map((part) => part.replace(/[.+?^${}()|[\]\\]/g, '\\$&')).join('[^/]*');
|
|
62
|
+
return new RegExp(`^${body}$`);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* What is wrong with a glob, or null. `**` only works as a whole path
|
|
66
|
+
* part (not `a**` or `**.user.js`), and not as the last one, which
|
|
67
|
+
* would leave the file name unmatched.
|
|
68
|
+
*/
|
|
69
|
+
export function globMistake(pattern) {
|
|
70
|
+
// A trailing slash leaves an empty last part, which isn't one.
|
|
71
|
+
const segments = pattern.split(SEPARATORS).filter(Boolean);
|
|
72
|
+
if (segments.some((s) => s.includes('**') && s !== '**')) {
|
|
73
|
+
return `Invalid glob ${quoted(pattern)}. Use ${quoted('**')} only as a whole path part, as in ${quoted('src/**/*.user.js')}.`;
|
|
74
|
+
}
|
|
75
|
+
if (segments.at(-1) === '**') {
|
|
76
|
+
return `Invalid glob ${quoted(pattern)}. It ends in ${quoted('**')}, so it names no files. Add a file name, as in ${quoted(`${pattern.replace(/[/\\]+$/, '')}/*.user.js`)}.`;
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The files a glob matches, sorted within each directory, no
|
|
82
|
+
* directories. The glob must have no globMistake.
|
|
83
|
+
*/
|
|
84
|
+
export function globFiles(pattern, cwd = process.cwd()) {
|
|
85
|
+
if (!pattern.includes('*'))
|
|
86
|
+
throw new Error('Internal error: globFiles needs a pattern with a *');
|
|
87
|
+
// `/`, or a drive's root (`C:\\`) on Windows; '' when relative.
|
|
88
|
+
const root = path.parse(pattern).root;
|
|
89
|
+
const segments = pattern.slice(root.length).split(SEPARATORS).filter(Boolean);
|
|
90
|
+
// The part before the first `*` is a plain directory to start from.
|
|
91
|
+
const firstGlob = segments.findIndex((s) => s.includes('*'));
|
|
92
|
+
const base = segments.slice(0, firstGlob);
|
|
93
|
+
const spelledBase = root || base.length > 0 ? path.join(root, ...base) : '';
|
|
94
|
+
const found = [];
|
|
95
|
+
const visit = (dir, spelled, rest) => {
|
|
96
|
+
const [segment, ...after] = rest;
|
|
97
|
+
const join = (name) => (spelled ? path.join(spelled, name) : name);
|
|
98
|
+
if (segment === '**') {
|
|
99
|
+
// Zero directories, then one more, and so on.
|
|
100
|
+
visit(dir, spelled, after);
|
|
101
|
+
for (const entry of entriesOf(dir)) {
|
|
102
|
+
if (!skipped(entry) && entry.isDirectory())
|
|
103
|
+
visit(path.join(dir, entry.name), join(entry.name), rest);
|
|
104
|
+
}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (!segment.includes('*')) {
|
|
108
|
+
const full = path.join(dir, segment);
|
|
109
|
+
if (after.length === 0) {
|
|
110
|
+
if (!isDirectory(full) && statOk(full))
|
|
111
|
+
found.push(join(segment));
|
|
112
|
+
}
|
|
113
|
+
else if (isDirectory(full)) {
|
|
114
|
+
visit(full, join(segment), after);
|
|
115
|
+
}
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const re = segmentRegExp(segment);
|
|
119
|
+
for (const entry of entriesOf(dir)) {
|
|
120
|
+
// A hidden name only for a segment that asks for one.
|
|
121
|
+
if (entry.name.startsWith('.') && !segment.startsWith('.'))
|
|
122
|
+
continue;
|
|
123
|
+
if (!re.test(entry.name))
|
|
124
|
+
continue;
|
|
125
|
+
// A link to a directory is followed here, where it was named.
|
|
126
|
+
const isDir = entry.isDirectory() || (entry.isSymbolicLink() && isDirectory(path.join(dir, entry.name)));
|
|
127
|
+
if (after.length === 0) {
|
|
128
|
+
if (!isDir)
|
|
129
|
+
found.push(join(entry.name));
|
|
130
|
+
}
|
|
131
|
+
else if (isDir) {
|
|
132
|
+
visit(path.join(dir, entry.name), join(entry.name), after);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
visit(path.resolve(cwd, spelledBase || '.'), spelledBase, segments.slice(firstGlob));
|
|
137
|
+
// `**/**` and the like can reach one file twice.
|
|
138
|
+
return [...new Set(found)];
|
|
139
|
+
}
|
|
140
|
+
function statOk(file) {
|
|
141
|
+
try {
|
|
142
|
+
statSync(file);
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type Chromium = typeof import('@playwright/test')['chromium'];
|
|
2
|
+
interface Playwright {
|
|
3
|
+
chromium: Chromium;
|
|
4
|
+
/** The command that installs the Chromium build it wants. */
|
|
5
|
+
install: string;
|
|
6
|
+
}
|
|
7
|
+
/** The repo's Playwright when it has one, else sm-dev's own. */
|
|
8
|
+
export declare function loadPlaywright(): Promise<Playwright>;
|
|
9
|
+
/**
|
|
10
|
+
* Why Playwright's Chromium at `executable` can't start, when it isn't
|
|
11
|
+
* installed: the Playwright version, the build it wants, the builds
|
|
12
|
+
* that are installed, and `install`, the command that installs it
|
|
13
|
+
* (from `loadPlaywright`). Null when it's there.
|
|
14
|
+
*/
|
|
15
|
+
export declare function missingChromium(executable: string, install?: string): string | null;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Which Playwright sm-dev drives browsers with, its own Chromium, and
|
|
2
|
+
// what to say when that Chromium isn't installed.
|
|
3
|
+
//
|
|
4
|
+
// - sm-dev uses the Playwright the repo has (`@playwright/test`, an
|
|
5
|
+
// optional peer dependency), so the fixture and the repo's own specs
|
|
6
|
+
// share one copy.
|
|
7
|
+
// - With none, as under `npx sm-dev`, it falls back to the
|
|
8
|
+
// `playwright-core` it depends on itself.
|
|
9
|
+
// - Each Playwright version wants one Chromium build, downloaded apart
|
|
10
|
+
// from the package (`pnpm install` doesn't fetch it) into a folder
|
|
11
|
+
// named for the build: `~/.cache/ms-playwright/chromium-1248/`.
|
|
12
|
+
// Updating Playwright leaves sm-dev wanting a build that isn't there
|
|
13
|
+
// yet, while the old one still is.
|
|
14
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
15
|
+
import { createRequire } from 'node:module';
|
|
16
|
+
import path from 'node:path';
|
|
17
|
+
import { quoted } from './output-style.js';
|
|
18
|
+
const REPO_INSTALL = 'pnpm exec playwright install chromium';
|
|
19
|
+
let loaded = null;
|
|
20
|
+
function isNotFound(e) {
|
|
21
|
+
const code = e?.code;
|
|
22
|
+
return code === 'ERR_MODULE_NOT_FOUND' || code === 'MODULE_NOT_FOUND';
|
|
23
|
+
}
|
|
24
|
+
function packageVersion(name) {
|
|
25
|
+
try {
|
|
26
|
+
return createRequire(import.meta.url)(`${name}/package.json`).version;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** The repo's Playwright when it has one, else sm-dev's own. */
|
|
33
|
+
export function loadPlaywright() {
|
|
34
|
+
loaded ??= (async () => {
|
|
35
|
+
try {
|
|
36
|
+
const { chromium } = await import('@playwright/test');
|
|
37
|
+
return { chromium, install: REPO_INSTALL };
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
if (!isNotFound(e))
|
|
41
|
+
throw e;
|
|
42
|
+
}
|
|
43
|
+
const { chromium } = await import('playwright-core');
|
|
44
|
+
// Pinned to the bundled version: a plain `npx playwright-core`
|
|
45
|
+
// fetches the newest, which wants a different build.
|
|
46
|
+
const version = packageVersion('playwright-core');
|
|
47
|
+
return {
|
|
48
|
+
chromium: chromium,
|
|
49
|
+
install: `npx playwright-core${version ? `@${version}` : ''} install chromium`,
|
|
50
|
+
};
|
|
51
|
+
})();
|
|
52
|
+
return loaded;
|
|
53
|
+
}
|
|
54
|
+
function playwrightVersion() {
|
|
55
|
+
return packageVersion('@playwright/test') ?? packageVersion('playwright-core');
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Why Playwright's Chromium at `executable` can't start, when it isn't
|
|
59
|
+
* installed: the Playwright version, the build it wants, the builds
|
|
60
|
+
* that are installed, and `install`, the command that installs it
|
|
61
|
+
* (from `loadPlaywright`). Null when it's there.
|
|
62
|
+
*/
|
|
63
|
+
export function missingChromium(executable, install = REPO_INSTALL) {
|
|
64
|
+
if (existsSync(executable))
|
|
65
|
+
return null;
|
|
66
|
+
const version = playwrightVersion();
|
|
67
|
+
const using = version ? `Playwright ${version}` : 'Playwright';
|
|
68
|
+
// The folder named for the build, above the executable.
|
|
69
|
+
let dir = path.dirname(executable);
|
|
70
|
+
while (!/^chromium-\d+$/.test(path.basename(dir)) && path.dirname(dir) !== dir)
|
|
71
|
+
dir = path.dirname(dir);
|
|
72
|
+
const build = /^chromium-(\d+)$/.exec(path.basename(dir))?.[1];
|
|
73
|
+
if (!build)
|
|
74
|
+
return `${using} needs Chromium at ${executable}, which isn't installed. Install it with ${quoted(install)}.`;
|
|
75
|
+
let installed = [];
|
|
76
|
+
try {
|
|
77
|
+
installed = readdirSync(path.dirname(dir)).map((name) => /^chromium-(\d+)$/.exec(name)?.[1])
|
|
78
|
+
// The wanted build's folder can be there without its executable,
|
|
79
|
+
// after an install that was cut off.
|
|
80
|
+
.filter((b) => !!b && b !== build);
|
|
81
|
+
}
|
|
82
|
+
catch { /* No browsers folder yet. */ }
|
|
83
|
+
const have = installed.length ? `(Installed builds: ${installed.join(', ')}.)` : '(No Chromium builds are installed.)';
|
|
84
|
+
return `${using} needs Chromium build ${build}, which isn't installed. ${have} `
|
|
85
|
+
+ `Install it with ${quoted(install)}. Run that again after each Playwright update.`;
|
|
86
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { type StoredScript, type ScriptMatching, type StartupLog } from '../script-build.js';
|
|
2
|
+
import { type DiagnosticLocation } from '../diagnostic-location.js';
|
|
3
|
+
import { type UrlMatchExplanation } from '../url-match.js';
|
|
4
|
+
import type { PushedFile } from '../external-files.js';
|
|
5
|
+
import { type InjectionWorld } from '../script-world.js';
|
|
6
|
+
export type { InjectionWorld };
|
|
7
|
+
export interface PrepareOptions {
|
|
8
|
+
/** Absolute path of the `.user.js` file. Either this or `text`. */
|
|
9
|
+
file?: string;
|
|
10
|
+
/** The script's source, when it isn't read from disk. */
|
|
11
|
+
text?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Where the script lives, as a URL. Relative `@require`s resolve
|
|
14
|
+
* against it, and only a `file://` script gets local overrides.
|
|
15
|
+
* Defaults to the file's own URL, or a placeholder `file://` URL
|
|
16
|
+
* next to `collectionRoot` when only `text` was given.
|
|
17
|
+
*/
|
|
18
|
+
sourceUrl?: string;
|
|
19
|
+
/**
|
|
20
|
+
* The directory the script's repo is rooted at. Searched for local
|
|
21
|
+
* stand-ins of remote `@require` / `@resource` URLs, so a script deep
|
|
22
|
+
* in `sites/` can reach a `lib/` at the top. The script's path is
|
|
23
|
+
* reported relative to it, as the extension would.
|
|
24
|
+
*/
|
|
25
|
+
collectionRoot?: string;
|
|
26
|
+
/** Extra directories to search for local stand-ins. */
|
|
27
|
+
localRoots?: string[];
|
|
28
|
+
/** Turn local stand-ins off entirely. Default on. */
|
|
29
|
+
localFiles?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Tells two loads of the same file apart, so both can run on one
|
|
32
|
+
* page as two installed copies would: each gets its own script id,
|
|
33
|
+
* its own storage, and its own wrapper. Without it a second load of
|
|
34
|
+
* a path replaces the first.
|
|
35
|
+
*/
|
|
36
|
+
copy?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Answers every `fetch` made while preparing (in practice, the
|
|
39
|
+
* `@require` / `@resource` fetches) in place of the network and
|
|
40
|
+
* disk, `file://` included. The corpus validator serves
|
|
41
|
+
* dependencies out of a downloaded tree this way.
|
|
42
|
+
*/
|
|
43
|
+
fetch?: (url: string) => Promise<Response>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Why the syntax check couldn't reach a verdict. The script stays `ok`
|
|
47
|
+
* (the check fails open, see docs/parse-check.md), so this is a warning:
|
|
48
|
+
* - `inconclusive`: V8 threw something other than a SyntaxError.
|
|
49
|
+
* - `errored`: composing the text to check threw.
|
|
50
|
+
*/
|
|
51
|
+
export interface ParseCheckNote {
|
|
52
|
+
kind: 'inconclusive' | 'errored';
|
|
53
|
+
message: string;
|
|
54
|
+
}
|
|
55
|
+
export interface PreparedScript {
|
|
56
|
+
/** The row the extension would have stored. */
|
|
57
|
+
script: StoredScript;
|
|
58
|
+
status: 'ok' | 'invalid';
|
|
59
|
+
/** The extension's own message, when `status` is `invalid`. */
|
|
60
|
+
errorMessage?: string;
|
|
61
|
+
errorLocation?: DiagnosticLocation;
|
|
62
|
+
/** `errorMessage` rendered with its location, as the viewer shows it. */
|
|
63
|
+
diagnostic?: string;
|
|
64
|
+
/** Non-fatal parse-time notes: an unknown `@grant`, an ignored `@match`. */
|
|
65
|
+
startupLogs: readonly StartupLog[];
|
|
66
|
+
/** Set when the syntax check couldn't decide; the script stays `ok`. */
|
|
67
|
+
parseCheckNote?: ParseCheckNote;
|
|
68
|
+
/**
|
|
69
|
+
* The run's id for the script, which the host maps to the extension's
|
|
70
|
+
* own once it's pushed (`setPushed`). Unset when invalid.
|
|
71
|
+
*/
|
|
72
|
+
id: string | undefined;
|
|
73
|
+
world: InjectionWorld;
|
|
74
|
+
matching: ScriptMatching;
|
|
75
|
+
/** The `@require` URLs, resolved, with where each was read from. */
|
|
76
|
+
requires: {
|
|
77
|
+
url: string;
|
|
78
|
+
localUrl?: string;
|
|
79
|
+
}[];
|
|
80
|
+
}
|
|
81
|
+
export declare function prepareScript(opts: PrepareOptions): Promise<PreparedScript>;
|
|
82
|
+
/**
|
|
83
|
+
* The roots to prepare `file` with, given `collectionRoot` and
|
|
84
|
+
* `localRoots`. A script outside the root it was given (sm-dev run in
|
|
85
|
+
* one repo on another's script, or a shared fixture's root) belongs to
|
|
86
|
+
* the collection whose `script_manifest.json` is nearest above it, as
|
|
87
|
+
* it would be installed. The given root then joins the local roots, so
|
|
88
|
+
* its `lib/` still stands in for the `@require`s that name it.
|
|
89
|
+
*/
|
|
90
|
+
export declare function scriptRoots(file: string, collectionRoot: string, localRoots?: string[]): {
|
|
91
|
+
collectionRoot: string;
|
|
92
|
+
localRoots: string[];
|
|
93
|
+
};
|
|
94
|
+
/** What a `ParseCheckNote` means for the person reading it. */
|
|
95
|
+
export declare function parseCheckWarning(note: ParseCheckNote): string;
|
|
96
|
+
/**
|
|
97
|
+
* Every warning from preparing the script, as `<level>: <message>`
|
|
98
|
+
* with the line each is about: the load-time notes the viewer's Log
|
|
99
|
+
* tab shows, then (unless `parseCheck` is false) a syntax check that
|
|
100
|
+
* couldn't decide.
|
|
101
|
+
*/
|
|
102
|
+
export declare function warningLines(prepared: PreparedScript, { parseCheck }?: {
|
|
103
|
+
parseCheck?: boolean | undefined;
|
|
104
|
+
}): string[];
|
|
105
|
+
export type MatchExplanation = UrlMatchExplanation;
|
|
106
|
+
/** The reason to give when no header rule names a URL at all. */
|
|
107
|
+
export declare const NO_RULE_COVERS_URL = "No @match or @include covers this URL";
|
|
108
|
+
/** The same, for `match` over several URLs, none of which a rule names. */
|
|
109
|
+
export declare const NO_RULE_COVERS_URLS = "No @match or @include covers these URLs";
|
|
110
|
+
/**
|
|
111
|
+
* Whether the script runs on `url`, and which header rule decided: an
|
|
112
|
+
* exclude wins over everything, then the first `@match`, then the
|
|
113
|
+
* first `@include`. Also every rule that matched or excluded it
|
|
114
|
+
* (`matchedBy`, `excludedBy`). The extension's own matcher, so the
|
|
115
|
+
* answer is the one the extension would give.
|
|
116
|
+
*/
|
|
117
|
+
export declare function explainMatch(matching: ScriptMatching, url: string): MatchExplanation;
|
|
118
|
+
/** A script path that names nothing, for `start` and the typed `load`. */
|
|
119
|
+
export declare function noSuchFileMessage(input: string): string;
|
|
120
|
+
/** A script path that names a directory, for `start` and the typed `load`. */
|
|
121
|
+
export declare function isDirectoryMessage(input: string, remedy?: string): string;
|
|
122
|
+
/** Why a script has no default page, as `--all` and `newtab all` report it. */
|
|
123
|
+
export declare const NO_DEFAULT_PAGE = "Its @match names no page to open";
|
|
124
|
+
/**
|
|
125
|
+
* The page a script is opened on when no URL is given: the first one
|
|
126
|
+
* its `@match` implies. Null when none names a page, as with a
|
|
127
|
+
* match-everything pattern.
|
|
128
|
+
*/
|
|
129
|
+
export declare function defaultPageUrl(script: PreparedScript): string | null;
|
|
130
|
+
/**
|
|
131
|
+
* A typed URL with `http://` added when it has no scheme, so
|
|
132
|
+
* `example.com/x` works. Only a word that starts with a host reads so:
|
|
133
|
+
* one with a dot, `localhost`, a port (`localhost:8080/x`) or an IPv6
|
|
134
|
+
* address (`[::1]/x`). Any other is a path, made a `file://` URL: one
|
|
135
|
+
* starting `/` or `.`, one naming a file that exists in `cwd`, or one
|
|
136
|
+
* whose first part has no dot (`pages/x.html`), existing or not. `host:port` would
|
|
137
|
+
* otherwise read as a scheme, so only a scheme followed by `//`, or one
|
|
138
|
+
* of the kinds that never have it, counts.
|
|
139
|
+
*/
|
|
140
|
+
export declare function withDefaultScheme(url: string, cwd?: string): string;
|
|
141
|
+
/**
|
|
142
|
+
* A path to show: relative to `cwd` when it's inside it, else
|
|
143
|
+
* `outside` (by default the full path). Never one climbing out with
|
|
144
|
+
* `../`, which is harder to read than either.
|
|
145
|
+
*/
|
|
146
|
+
export declare function shownPath(file: string, cwd?: string, outside?: string): string;
|
|
147
|
+
/**
|
|
148
|
+
* Where a loaded script is, to show beside its name (`shownPath`).
|
|
149
|
+
* Its `relativePath` stays what identifies it, as in the extension.
|
|
150
|
+
*/
|
|
151
|
+
export declare function preparedScriptPath(script: PreparedScript): string;
|
|
152
|
+
/** The script's `@name`, else the path it was loaded from. */
|
|
153
|
+
export declare function preparedScriptName(script: PreparedScript): string;
|
|
154
|
+
/** Whether the script has `@noframes`, which keeps it to the top frame. */
|
|
155
|
+
export declare function preparedNoframes(script: PreparedScript): boolean;
|
|
156
|
+
/**
|
|
157
|
+
* Whether `name` picks out this script: the path it was loaded from,
|
|
158
|
+
* its basename, or its `@name`. How a test or a typed command names
|
|
159
|
+
* one script among several.
|
|
160
|
+
*/
|
|
161
|
+
export declare function preparedScriptMatches(script: PreparedScript, name: string): boolean;
|
|
162
|
+
/**
|
|
163
|
+
* The `@require` / `@resource` bodies a run pushes into SourceMonkey with
|
|
164
|
+
* the script's text, by the ref its header declares: those read from
|
|
165
|
+
* disk, a relative ref's file or a local stand-in for a remote URL,
|
|
166
|
+
* which the extension couldn't read itself. Remote ones it fetches.
|
|
167
|
+
*/
|
|
168
|
+
export declare function pushedFiles(prepared: PreparedScript): Record<string, PushedFile>;
|