@1aboveio/skills 0.19.3 → 0.20.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.
- package/README.md +9 -4
- package/package.json +1 -1
- package/runtime/skills/distribution/generated/recipes.json +54 -48
- package/runtime/skills/distribution/scripts/bundles.mjs +113 -7
- package/runtime/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +4 -6
- package/runtime/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +3 -36
- package/skills/cicd-pipeline/cloud-build/SKILL.md +6 -6
- package/skills/cicd-pipeline/mergify/SKILL.md +1 -1
- package/skills/engineering/engineering-runtime/coherence/workflow.json +15 -84
- package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +4 -6
- package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +3 -36
- package/skills/engineering/rush-release/SKILL.md +46 -25
- package/skills/engineering/rush-release/evals/evals.json +22 -8
- package/skills/engineering/rush-release/references/cut.md +21 -4
- package/skills/engineering/rush-release/references/preflight.md +25 -6
- package/skills/engineering/rush-release/references/promotion.md +70 -0
- package/skills/engineering/rush-release/references/publish.md +49 -16
- package/skills/engineering/rush-release/scripts/plan.mjs +33 -7
- package/skills/engineering/smoke/SKILL.md +4 -4
- package/skills/engineering/smoke/references/manifest.md +3 -3
- package/skills/payment/payment-analysis/SKILL.md +5 -3
- package/skills/payment/tld-detection/SKILL.md +163 -0
- package/skills/payment/tld-detection/agents/openai.yaml +9 -0
- package/skills/payment/tld-detection/evals/evals.json +107 -0
- package/skills/payment/tld-detection/references/clean.md +51 -0
- package/skills/payment/tld-detection/references/clustering.md +219 -0
- package/skills/payment/tld-detection/references/decision.md +85 -0
- package/skills/payment/tld-detection/references/report-template.md +169 -0
- package/skills/payment/tld-detection/references/terminology.md +69 -0
- package/skills/payment/tld-detection/references/workflow.md +78 -0
- package/skills/payment/tld-detection/scripts/detect_ladders.py +390 -0
- package/skills/payment/tld-detection/tests/test_detect_ladders.py +132 -0
- package/skills/engineering/resolve-issues/SKILL.md +0 -168
- package/skills/engineering/resolve-issues/agents/openai.yaml +0 -9
- package/skills/engineering/resolve-issues/generated/workflow-repair-policy.json +0 -499
- package/skills/engineering/resolve-issues/references/breaker.md +0 -82
- package/skills/engineering/resolve-issues/references/deliverables.md +0 -27
- package/skills/engineering/resolve-issues/references/delivery.md +0 -108
- package/skills/engineering/resolve-issues/references/evidence-lane.md +0 -21
- package/skills/engineering/resolve-issues/references/exact-head-ci.md +0 -287
- package/skills/engineering/resolve-issues/references/fan-out.md +0 -33
- package/skills/engineering/resolve-issues/references/finalization.md +0 -68
- package/skills/engineering/resolve-issues/references/guarantees.md +0 -10
- package/skills/engineering/resolve-issues/references/high-risk.md +0 -29
- package/skills/engineering/resolve-issues/references/incidents/848/README.md +0 -156
- package/skills/engineering/resolve-issues/references/intake.md +0 -86
- package/skills/engineering/resolve-issues/references/integration-gate.md +0 -53
- package/skills/engineering/resolve-issues/references/interference.md +0 -87
- package/skills/engineering/resolve-issues/references/loop.md +0 -134
- package/skills/engineering/resolve-issues/references/model-catalog.md +0 -9
- package/skills/engineering/resolve-issues/references/postmortem.md +0 -27
- package/skills/engineering/resolve-issues/references/pre-flight-model-slots.md +0 -41
- package/skills/engineering/resolve-issues/references/pre-flight-recording-and-checkout.md +0 -48
- package/skills/engineering/resolve-issues/references/pre-flight.md +0 -41
- package/skills/engineering/resolve-issues/references/regression-checklist.md +0 -26
- package/skills/engineering/resolve-issues/references/run-state.md +0 -288
- package/skills/engineering/resolve-issues/references/sandboxed-testing.md +0 -48
- package/skills/engineering/resolve-issues/references/spawn-contract.md +0 -96
- package/skills/engineering/resolve-issues/references/terminal-evidence-journal.md +0 -40
- package/skills/engineering/resolve-issues/references/why.md +0 -653
- package/skills/engineering/resolve-issues/schemas/fix-round.schema.json +0 -49
- package/skills/engineering/resolve-issues/scripts/combine-and-verify.mjs +0 -721
- package/skills/engineering/resolve-issues/scripts/component-candidate.mjs +0 -962
- package/skills/engineering/resolve-issues/scripts/contract-revision.mjs +0 -220
- package/skills/engineering/resolve-issues/scripts/detect-delivery-mode.mjs +0 -420
- package/skills/engineering/resolve-issues/scripts/detect-target-branch.mjs +0 -256
- package/skills/engineering/resolve-issues/scripts/detect-workspace-mode.mjs +0 -168
- package/skills/engineering/resolve-issues/scripts/discover-models.mjs +0 -9
- package/skills/engineering/resolve-issues/scripts/doctrine.mjs +0 -62
- package/skills/engineering/resolve-issues/scripts/evidence-lifecycle-contract.mjs +0 -191
- package/skills/engineering/resolve-issues/scripts/exact-head-ci.mjs +0 -413
- package/skills/engineering/resolve-issues/scripts/exact-head-github-provider.mjs +0 -332
- package/skills/engineering/resolve-issues/scripts/finalize.mjs +0 -488
- package/skills/engineering/resolve-issues/scripts/fix-rounds.mjs +0 -3307
- package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-circular-1001.json +0 -16
- package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-valid-sequencing.json +0 -51
- package/skills/engineering/resolve-issues/scripts/fixtures/fmm-express-830-component-candidate.json +0 -17
- package/skills/engineering/resolve-issues/scripts/fixtures/head-check-set-1081.json +0 -166
- package/skills/engineering/resolve-issues/scripts/gate-value-series.mjs +0 -92
- package/skills/engineering/resolve-issues/scripts/guide-index.mjs +0 -73
- package/skills/engineering/resolve-issues/scripts/head-check-set.mjs +0 -159
- package/skills/engineering/resolve-issues/scripts/interference.mjs +0 -427
- package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +0 -9
- package/skills/engineering/resolve-issues/scripts/next-operations.mjs +0 -419
- package/skills/engineering/resolve-issues/scripts/postmortem.mjs +0 -909
- package/skills/engineering/resolve-issues/scripts/preflight-questions.mjs +0 -345
- package/skills/engineering/resolve-issues/scripts/reconcile-contained-unit-prs.mjs +0 -415
- package/skills/engineering/resolve-issues/scripts/release-state-contract.mjs +0 -697
- package/skills/engineering/resolve-issues/scripts/report.mjs +0 -494
- package/skills/engineering/resolve-issues/scripts/required-check-plan.mjs +0 -172
- package/skills/engineering/resolve-issues/scripts/round-metadata.mjs +0 -79
- package/skills/engineering/resolve-issues/scripts/run-state-review6-cases.mjs +0 -334
- package/skills/engineering/resolve-issues/scripts/run-state.mjs +0 -4792
- package/skills/engineering/resolve-issues/scripts/sandbox-selftest.mjs +0 -395
- package/skills/engineering/resolve-issues/scripts/spawn-contract.mjs +0 -290
- package/skills/engineering/resolve-issues/scripts/terminal-dispositions.mjs +0 -170
- package/skills/engineering/resolve-issues/scripts/terminal-evidence-journal.mjs +0 -293
- package/skills/engineering/resolve-issues/scripts/unit-kind.mjs +0 -197
- package/skills/engineering/resolve-issues/scripts/unit-lifecycle.mjs +0 -127
- package/skills/engineering/resolve-issues/scripts/watch-delivery.mjs +0 -893
- package/skills/engineering/resolve-issues/scripts/workspaces.mjs +0 -829
- package/skills/engineering/resolve-issues/workflows/independent-review.workflow.js +0 -290
- package/skills/engineering/resolve-issues/workflows/prior-art-scan.workflow.js +0 -80
- package/skills/engineering/resolve-issues/workflows/workflow-smoke.mjs +0 -102
- package/skills/engineering/resolve-release/LICENSE +0 -3
- package/skills/engineering/resolve-release/SKILL.md +0 -113
- package/skills/engineering/resolve-release/agents/openai.yaml +0 -9
- package/skills/engineering/resolve-release/references/assembly.md +0 -137
- package/skills/engineering/resolve-release/references/auto-when-green.md +0 -56
- package/skills/engineering/resolve-release/references/candidate.md +0 -167
- package/skills/engineering/resolve-release/references/exposure.md +0 -178
- package/skills/engineering/resolve-release/references/handoff.md +0 -24
- package/skills/engineering/resolve-release/references/postmortem.md +0 -230
- package/skills/engineering/resolve-release/references/preflight.md +0 -208
- package/skills/engineering/resolve-release/references/principles.md +0 -94
- package/skills/engineering/resolve-release/references/regression-checklist.md +0 -36
- package/skills/engineering/resolve-release/references/related-skills.md +0 -13
- package/skills/engineering/resolve-release/references/routing.md +0 -149
- package/skills/engineering/resolve-release/references/verified-sha-github-flow.md +0 -285
- package/skills/engineering/resolve-release/references/versioning.md +0 -202
- package/skills/engineering/resolve-release/references/why.md +0 -53
- package/skills/engineering/resolve-release/scripts/adapter-completion-artifact.mjs +0 -389
- package/skills/engineering/resolve-release/scripts/build-changes.mjs +0 -209
- package/skills/engineering/resolve-release/scripts/candidate-hygiene.mjs +0 -407
- package/skills/engineering/resolve-release/scripts/candidate-identity.mjs +0 -904
- package/skills/engineering/resolve-release/scripts/candidate-traffic.mjs +0 -81
- package/skills/engineering/resolve-release/scripts/checked-adapter-loader.mjs +0 -612
- package/skills/engineering/resolve-release/scripts/close-attempt.mjs +0 -135
- package/skills/engineering/resolve-release/scripts/closeout-release.mjs +0 -161
- package/skills/engineering/resolve-release/scripts/doctrine.mjs +0 -106
- package/skills/engineering/resolve-release/scripts/durable-processing.mjs +0 -522
- package/skills/engineering/resolve-release/scripts/ensure-target-green.mjs +0 -659
- package/skills/engineering/resolve-release/scripts/evidence-bundle.mjs +0 -1014
- package/skills/engineering/resolve-release/scripts/finalize-release.mjs +0 -526
- package/skills/engineering/resolve-release/scripts/fixtures/durable-processing-adapter.mjs +0 -169
- package/skills/engineering/resolve-release/scripts/green-gate.mjs +0 -599
- package/skills/engineering/resolve-release/scripts/isolated-adapter-evaluator.mjs +0 -752
- package/skills/engineering/resolve-release/scripts/metadata-pr-status.mjs +0 -56
- package/skills/engineering/resolve-release/scripts/metadata-sync.mjs +0 -1538
- package/skills/engineering/resolve-release/scripts/postmortem.mjs +0 -381
- package/skills/engineering/resolve-release/scripts/preflight-probes.mjs +0 -510
- package/skills/engineering/resolve-release/scripts/production-endpoints.mjs +0 -326
- package/skills/engineering/resolve-release/scripts/rc-circuit-breaker.mjs +0 -272
- package/skills/engineering/resolve-release/scripts/report.mjs +0 -417
- package/skills/engineering/resolve-release/scripts/reprobe-credentials.mjs +0 -114
- package/skills/engineering/resolve-release/scripts/revalidate-candidate.mjs +0 -238
- package/skills/engineering/resolve-release/scripts/review-packet.mjs +0 -503
- package/skills/engineering/resolve-release/scripts/rollback-floor.mjs +0 -263
- package/skills/engineering/resolve-release/scripts/version-assert.mjs +0 -339
- package/skills/engineering/resolve-release/scripts/version-postmortem.mjs +0 -485
- package/skills/engineering/resolve-release/scripts/version.mjs +0 -1199
- package/skills/engineering/resolve-release/scripts/watch-candidate-delivery.mjs +0 -449
- package/skills/engineering/resolve-release/vendor/ACORN-LICENSE +0 -21
- package/skills/engineering/resolve-release/vendor/README.md +0 -60
- package/skills/engineering/resolve-release/vendor/acorn.mjs +0 -6233
- package/skills/engineering/resolve-release/vendor/quickjs/core/LICENSE +0 -21
- package/skills/engineering/resolve-release/vendor/quickjs/core/README.md +0 -341
- package/skills/engineering/resolve-release/vendor/quickjs/core/README.template.md +0 -70
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs +0 -7
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.mts +0 -2033
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.ts +0 -2033
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js +0 -7
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/core/package.json +0 -49
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/LICENSE +0 -21
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/README.md +0 -5
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.mts +0 -549
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.ts +0 -549
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/package.json +0 -36
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/LICENSE +0 -47
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/README.md +0 -82
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.d.ts +0 -11
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.mjs +0 -22
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cjs +0 -21
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.cjs +0 -21
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.d.ts +0 -11
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.d.ts +0 -11
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.mjs +0 -25
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.wasm +0 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.mts +0 -85
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.ts +0 -85
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.mts +0 -20
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.ts +0 -20
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs +0 -2
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs.map +0 -1
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/package.json +0 -61
- /package/skills/{engineering/resolve-issues → payment/tld-detection}/LICENSE +0 -0
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
// Shared Cloud Run traffic capture parser for candidate discovery and hygiene.
|
|
2
|
-
|
|
3
|
-
// Cloud Run omits percent for zero-traffic tagged targets. Absence remains null unless the
|
|
4
|
-
// complete observation proves every omitted target has the only remaining share: zero.
|
|
5
|
-
export function parseTraffic(text) {
|
|
6
|
-
const trimmed = String(text ?? '').trim()
|
|
7
|
-
if (trimmed.startsWith('[') || trimmed.startsWith('{')) {
|
|
8
|
-
let parsed
|
|
9
|
-
try {
|
|
10
|
-
parsed = JSON.parse(trimmed)
|
|
11
|
-
} catch {
|
|
12
|
-
return { error: 'traffic read is not parseable as JSON' }
|
|
13
|
-
}
|
|
14
|
-
// Accept either a bare traffic array or a full service describe whose status.traffic is
|
|
15
|
-
// the array — the JSON recipe pipes either shape without a second jq pass.
|
|
16
|
-
if (parsed && !Array.isArray(parsed) && typeof parsed === 'object') {
|
|
17
|
-
const traffic = parsed.status && parsed.status.traffic
|
|
18
|
-
if (Array.isArray(traffic)) parsed = traffic
|
|
19
|
-
else return { error: 'traffic JSON object has no status.traffic array' }
|
|
20
|
-
}
|
|
21
|
-
if (!Array.isArray(parsed)) return { error: 'traffic JSON is not an array of traffic targets' }
|
|
22
|
-
const rows = parsed.map((r) => ({
|
|
23
|
-
tag: str(r && r.tag),
|
|
24
|
-
url: str(r && r.url),
|
|
25
|
-
revision: str(r && (r.revisionName ?? r.revision)),
|
|
26
|
-
percent: r && Object.hasOwn(r, 'percent') ? explicitPercent(r.percent) : null,
|
|
27
|
-
}))
|
|
28
|
-
return { rows: normalizeTrafficPercents(rows) }
|
|
29
|
-
}
|
|
30
|
-
const rows = trimmed
|
|
31
|
-
.split('\n')
|
|
32
|
-
.map((l) => l.replace(/\r$/, ''))
|
|
33
|
-
.filter((l) => l.trim().length > 0)
|
|
34
|
-
.map((l) => {
|
|
35
|
-
// gcloud separates value() columns with TABs; tolerate a multi-space separator too,
|
|
36
|
-
// which is what a human pasting a terminal capture into a file produces.
|
|
37
|
-
const cells = l.includes('\t') ? l.split('\t') : l.split(/\s{2,}/)
|
|
38
|
-
const [tag, url, revision, percent] = cells
|
|
39
|
-
return { tag: str(tag), url: str(url), revision: str(revision), percent: num(percent) }
|
|
40
|
-
})
|
|
41
|
-
return { rows: normalizeTrafficPercents(rows) }
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// A conservation proof is valid only when every explicit target is a finite percentage in
|
|
45
|
-
// [0, 100] and those explicit targets already account for the full 100%. The remaining
|
|
46
|
-
// omitted rows must then each be zero; any partial, overfull, negative, or invalid observation
|
|
47
|
-
// remains ambiguous.
|
|
48
|
-
export function normalizeTrafficPercents(rows) {
|
|
49
|
-
if (!Array.isArray(rows) || rows.length === 0) return rows
|
|
50
|
-
const omitted = []
|
|
51
|
-
let explicitSum = 0
|
|
52
|
-
for (let i = 0; i < rows.length; i++) {
|
|
53
|
-
const percent = rows[i].percent
|
|
54
|
-
if (percent === null) {
|
|
55
|
-
omitted.push(i)
|
|
56
|
-
continue
|
|
57
|
-
}
|
|
58
|
-
if (!Number.isFinite(percent) || percent < 0 || percent > 100) return rows
|
|
59
|
-
explicitSum += percent
|
|
60
|
-
}
|
|
61
|
-
if (omitted.length === 0 || explicitSum !== 100) return rows
|
|
62
|
-
const normalized = rows.map((row) => ({ ...row }))
|
|
63
|
-
for (const index of omitted) normalized[index].percent = 0
|
|
64
|
-
return normalized
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const explicitPercent = (value) => {
|
|
68
|
-
const parsed = num(value)
|
|
69
|
-
return parsed === null ? Number.NaN : parsed
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export const str = (v) => (typeof v === 'string' ? v.trim() : v === undefined || v === null ? '' : String(v).trim())
|
|
73
|
-
// An ABSENT percent is null, not 0. `Number('')` is 0, so the obvious form reads a column the
|
|
74
|
-
// platform never supplied as the one value that means "no users are reaching this" — absent
|
|
75
|
-
// evidence rendered as the passing answer, which is the failure this whole script exists to stop.
|
|
76
|
-
const num = (v) => {
|
|
77
|
-
const s = str(v)
|
|
78
|
-
if (s.length === 0) return null
|
|
79
|
-
const n = Number(s)
|
|
80
|
-
return Number.isFinite(n) ? n : Number.NaN
|
|
81
|
-
}
|
|
@@ -1,612 +0,0 @@
|
|
|
1
|
-
import crypto from 'node:crypto'
|
|
2
|
-
import fs from 'node:fs'
|
|
3
|
-
import path from 'node:path'
|
|
4
|
-
import { TextDecoder } from 'node:util'
|
|
5
|
-
import { parse, version as acornVersion } from '../vendor/acorn.mjs'
|
|
6
|
-
import { inspectIsolatedAdapter } from './isolated-adapter-evaluator.mjs'
|
|
7
|
-
|
|
8
|
-
// Adapters are deliberately small policy modules. The bound prevents an approved path
|
|
9
|
-
// from becoming an unbounded memory/input surface before JavaScript parsing.
|
|
10
|
-
export const CHECKED_ADAPTER_MAX_BYTES = 256 * 1024
|
|
11
|
-
export const CHECKED_ADAPTER_PARSER = Object.freeze({
|
|
12
|
-
name: 'acorn',
|
|
13
|
-
version: acornVersion,
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
const FORBIDDEN_DEPENDENCY = 'e:adapter-dependency-forbidden'
|
|
17
|
-
const FORBIDDEN_CAPABILITY = 'e:adapter-capability-forbidden'
|
|
18
|
-
export const CHECKED_ADAPTER_ALLOWED_GLOBALS = Object.freeze([
|
|
19
|
-
'AggregateError', 'Array', 'BigInt', 'Boolean', 'Date', 'Error', 'EvalError',
|
|
20
|
-
'Infinity', 'JSON', 'Math', 'NaN', 'Number', 'Object', 'RangeError',
|
|
21
|
-
'ReferenceError', 'RegExp', 'String', 'SyntaxError', 'TypeError', 'URIError',
|
|
22
|
-
'console', 'undefined',
|
|
23
|
-
])
|
|
24
|
-
const ALLOWED_GLOBALS = new Set(CHECKED_ADAPTER_ALLOWED_GLOBALS)
|
|
25
|
-
const FORBIDDEN_PROPERTIES = new Set([
|
|
26
|
-
'__proto__',
|
|
27
|
-
'_linkedBinding',
|
|
28
|
-
'__defineGetter__',
|
|
29
|
-
'__defineSetter__',
|
|
30
|
-
'__lookupGetter__',
|
|
31
|
-
'__lookupSetter__',
|
|
32
|
-
'AsyncFunction',
|
|
33
|
-
'AsyncGeneratorFunction',
|
|
34
|
-
'apply',
|
|
35
|
-
'bind',
|
|
36
|
-
'binding',
|
|
37
|
-
'call',
|
|
38
|
-
'compile',
|
|
39
|
-
'compileFunction',
|
|
40
|
-
'compileStreaming',
|
|
41
|
-
'constructor',
|
|
42
|
-
'createRequire',
|
|
43
|
-
'dlopen',
|
|
44
|
-
'eval',
|
|
45
|
-
'Function',
|
|
46
|
-
'GeneratorFunction',
|
|
47
|
-
'getBuiltinModule',
|
|
48
|
-
'getOwnPropertyDescriptor',
|
|
49
|
-
'getOwnPropertyDescriptors',
|
|
50
|
-
'getOwnPropertyNames',
|
|
51
|
-
'getOwnPropertySymbols',
|
|
52
|
-
'getPrototypeOf',
|
|
53
|
-
'global',
|
|
54
|
-
'globalThis',
|
|
55
|
-
'instantiate',
|
|
56
|
-
'instantiateStreaming',
|
|
57
|
-
'module',
|
|
58
|
-
'Module',
|
|
59
|
-
'_load',
|
|
60
|
-
'_resolveFilename',
|
|
61
|
-
'register',
|
|
62
|
-
'registerHooks',
|
|
63
|
-
'runInContext',
|
|
64
|
-
'runInNewContext',
|
|
65
|
-
'runInThisContext',
|
|
66
|
-
'SourceTextModule',
|
|
67
|
-
'SyntheticModule',
|
|
68
|
-
'process',
|
|
69
|
-
'prototype',
|
|
70
|
-
'require',
|
|
71
|
-
'setPrototypeOf',
|
|
72
|
-
'WebAssembly',
|
|
73
|
-
])
|
|
74
|
-
const UTF8_DECODER = new TextDecoder('utf-8', { fatal: true })
|
|
75
|
-
const MODULE_CACHE = new Map()
|
|
76
|
-
|
|
77
|
-
export class CheckedAdapterError extends Error {
|
|
78
|
-
constructor(code) {
|
|
79
|
-
super(code)
|
|
80
|
-
this.name = 'CheckedAdapterError'
|
|
81
|
-
this.code = code
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function fail(code) {
|
|
86
|
-
throw new CheckedAdapterError(code)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function contained(root, candidate) {
|
|
90
|
-
const relative = path.relative(root, candidate)
|
|
91
|
-
return relative !== '..'
|
|
92
|
-
&& !relative.startsWith(`..${path.sep}`)
|
|
93
|
-
&& !path.isAbsolute(relative)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function canonical(file, code) {
|
|
97
|
-
try {
|
|
98
|
-
return fs.realpathSync(file)
|
|
99
|
-
} catch {
|
|
100
|
-
fail(code)
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function stat(file, code) {
|
|
105
|
-
try {
|
|
106
|
-
return fs.statSync(file, { bigint: true })
|
|
107
|
-
} catch {
|
|
108
|
-
fail(code)
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function sameIdentity(left, right) {
|
|
113
|
-
return left.dev === right.dev
|
|
114
|
-
&& left.ino === right.ino
|
|
115
|
-
&& left.mode === right.mode
|
|
116
|
-
&& left.size === right.size
|
|
117
|
-
&& left.mtimeNs === right.mtimeNs
|
|
118
|
-
&& left.ctimeNs === right.ctimeNs
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function notifyFilesystemBoundary(hook, phase) {
|
|
122
|
-
if (hook == null) return
|
|
123
|
-
if (typeof hook !== 'function') fail('e:adapter-loader-seam-invalid')
|
|
124
|
-
hook(Object.freeze({ phase }))
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function openChecked(file) {
|
|
128
|
-
const noFollow = Number.isInteger(fs.constants.O_NOFOLLOW) ? fs.constants.O_NOFOLLOW : 0
|
|
129
|
-
const nonblock = Number.isInteger(fs.constants.O_NONBLOCK) ? fs.constants.O_NONBLOCK : 0
|
|
130
|
-
try {
|
|
131
|
-
return fs.openSync(file, fs.constants.O_RDONLY | noFollow | nonblock)
|
|
132
|
-
} catch {
|
|
133
|
-
fail('e:adapter-unloadable')
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function readBounded(fd, expectedSize) {
|
|
138
|
-
const size = Number(expectedSize)
|
|
139
|
-
const bytes = Buffer.alloc(size)
|
|
140
|
-
let offset = 0
|
|
141
|
-
while (offset < size) {
|
|
142
|
-
const count = fs.readSync(fd, bytes, offset, size - offset, offset)
|
|
143
|
-
if (count === 0) fail('e:adapter-changed-during-acquisition')
|
|
144
|
-
offset += count
|
|
145
|
-
}
|
|
146
|
-
const extra = Buffer.alloc(1)
|
|
147
|
-
if (fs.readSync(fd, extra, 0, 1, offset) !== 0) fail('e:adapter-changed-during-acquisition')
|
|
148
|
-
return bytes
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function acquireSource(repositoryRoot, adapterPath, hook) {
|
|
152
|
-
if (typeof repositoryRoot !== 'string' || repositoryRoot.trim() === '') {
|
|
153
|
-
fail('e:repository-root-unreadable')
|
|
154
|
-
}
|
|
155
|
-
if (typeof adapterPath !== 'string' || adapterPath.trim() === '') fail('e:adapter-undeclared')
|
|
156
|
-
if (path.isAbsolute(adapterPath)) fail('e:adapter-outside-repository')
|
|
157
|
-
|
|
158
|
-
const lexicalRoot = path.resolve(repositoryRoot)
|
|
159
|
-
const lexicalAdapter = path.resolve(lexicalRoot, adapterPath)
|
|
160
|
-
if (!contained(lexicalRoot, lexicalAdapter)) fail('e:adapter-outside-repository')
|
|
161
|
-
|
|
162
|
-
const canonicalRoot = canonical(lexicalRoot, 'e:repository-root-unreadable')
|
|
163
|
-
const canonicalAdapter = canonical(lexicalAdapter, 'e:adapter-unloadable')
|
|
164
|
-
if (!contained(canonicalRoot, canonicalAdapter)) fail('e:adapter-outside-repository')
|
|
165
|
-
if (path.extname(canonicalAdapter) !== '.mjs') fail('e:adapter-not-module')
|
|
166
|
-
|
|
167
|
-
const approved = stat(canonicalAdapter, 'e:adapter-unloadable')
|
|
168
|
-
if (!approved.isFile()) fail('e:adapter-not-regular-file')
|
|
169
|
-
if (approved.size > BigInt(CHECKED_ADAPTER_MAX_BYTES)) fail('e:adapter-too-large')
|
|
170
|
-
|
|
171
|
-
notifyFilesystemBoundary(hook, 'before-open')
|
|
172
|
-
const fd = openChecked(canonicalAdapter)
|
|
173
|
-
let bytes
|
|
174
|
-
let opened
|
|
175
|
-
let acquisitionError
|
|
176
|
-
try {
|
|
177
|
-
opened = fs.fstatSync(fd, { bigint: true })
|
|
178
|
-
if (!opened.isFile()) fail('e:adapter-not-regular-file')
|
|
179
|
-
if (opened.size > BigInt(CHECKED_ADAPTER_MAX_BYTES)) fail('e:adapter-too-large')
|
|
180
|
-
if (!sameIdentity(approved, opened)) fail('e:adapter-replaced-before-open')
|
|
181
|
-
notifyFilesystemBoundary(hook, 'after-open')
|
|
182
|
-
const afterOpenPath = stat(canonicalAdapter, 'e:adapter-replaced-after-open')
|
|
183
|
-
if (!sameIdentity(opened, afterOpenPath)) {
|
|
184
|
-
fail('e:adapter-replaced-after-open')
|
|
185
|
-
}
|
|
186
|
-
notifyFilesystemBoundary(hook, 'before-read')
|
|
187
|
-
bytes = readBounded(fd, opened.size)
|
|
188
|
-
const afterRead = fs.fstatSync(fd, { bigint: true })
|
|
189
|
-
if (!sameIdentity(opened, afterRead)) fail('e:adapter-changed-during-acquisition')
|
|
190
|
-
} catch (error) {
|
|
191
|
-
acquisitionError = error instanceof CheckedAdapterError
|
|
192
|
-
? error
|
|
193
|
-
: new CheckedAdapterError('e:adapter-unloadable')
|
|
194
|
-
} finally {
|
|
195
|
-
try {
|
|
196
|
-
fs.closeSync(fd)
|
|
197
|
-
} catch {
|
|
198
|
-
if (acquisitionError == null) acquisitionError = new CheckedAdapterError('e:adapter-close-failed')
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
if (acquisitionError != null) throw acquisitionError
|
|
202
|
-
|
|
203
|
-
const finalCanonical = canonical(lexicalAdapter, 'e:adapter-replaced-after-open')
|
|
204
|
-
if (finalCanonical !== canonicalAdapter || !contained(canonicalRoot, finalCanonical)) {
|
|
205
|
-
fail('e:adapter-replaced-after-open')
|
|
206
|
-
}
|
|
207
|
-
const finalStat = stat(finalCanonical, 'e:adapter-replaced-after-open')
|
|
208
|
-
if (!sameIdentity(opened, finalStat)) fail('e:adapter-replaced-after-open')
|
|
209
|
-
|
|
210
|
-
return Object.freeze({ bytes, canonicalPath: canonicalAdapter })
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
function decodeStrictUtf8(bytes) {
|
|
214
|
-
try {
|
|
215
|
-
return UTF8_DECODER.decode(bytes)
|
|
216
|
-
} catch {
|
|
217
|
-
fail('e:adapter-invalid-utf8')
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
function children(node) {
|
|
222
|
-
const values = []
|
|
223
|
-
for (const [key, value] of Object.entries(node)) {
|
|
224
|
-
if (key === 'start' || key === 'end' || key === 'loc') continue
|
|
225
|
-
if (Array.isArray(value)) values.push(...value)
|
|
226
|
-
else values.push(value)
|
|
227
|
-
}
|
|
228
|
-
return values.filter((value) => value != null && typeof value === 'object')
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
function staticPropertyName(node) {
|
|
232
|
-
if (node == null) return null
|
|
233
|
-
if (node.type === 'Identifier' || node.type === 'PrivateIdentifier') return node.name
|
|
234
|
-
if (node.type === 'Literal' && (typeof node.value === 'string' || typeof node.value === 'number')) {
|
|
235
|
-
return String(node.value)
|
|
236
|
-
}
|
|
237
|
-
return null
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
function childEntries(node) {
|
|
241
|
-
const entries = []
|
|
242
|
-
for (const [key, value] of Object.entries(node)) {
|
|
243
|
-
if (key === 'start' || key === 'end' || key === 'loc') continue
|
|
244
|
-
if (Array.isArray(value)) {
|
|
245
|
-
for (const child of value) {
|
|
246
|
-
if (child != null && typeof child === 'object') entries.push([key, child])
|
|
247
|
-
}
|
|
248
|
-
} else if (value != null && typeof value === 'object') {
|
|
249
|
-
entries.push([key, value])
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
return entries
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
function newScope(parent, varScope = false) {
|
|
256
|
-
const scope = { parent, bindings: new Set(), varScope: null }
|
|
257
|
-
scope.varScope = varScope ? scope : parent?.varScope
|
|
258
|
-
return scope
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
function declarePattern(pattern, scope) {
|
|
262
|
-
if (pattern == null) return
|
|
263
|
-
if (pattern.type === 'Identifier') {
|
|
264
|
-
scope.bindings.add(pattern.name)
|
|
265
|
-
return
|
|
266
|
-
}
|
|
267
|
-
if (pattern.type === 'RestElement') {
|
|
268
|
-
declarePattern(pattern.argument, scope)
|
|
269
|
-
return
|
|
270
|
-
}
|
|
271
|
-
if (pattern.type === 'AssignmentPattern') {
|
|
272
|
-
declarePattern(pattern.left, scope)
|
|
273
|
-
return
|
|
274
|
-
}
|
|
275
|
-
if (pattern.type === 'ArrayPattern') {
|
|
276
|
-
for (const element of pattern.elements) declarePattern(element, scope)
|
|
277
|
-
return
|
|
278
|
-
}
|
|
279
|
-
if (pattern.type === 'ObjectPattern') {
|
|
280
|
-
for (const property of pattern.properties) {
|
|
281
|
-
if (property.type === 'RestElement') declarePattern(property.argument, scope)
|
|
282
|
-
else declarePattern(property.value, scope)
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
function buildScopeModel(ast) {
|
|
288
|
-
const scopeAt = new WeakMap()
|
|
289
|
-
const root = newScope(null, true)
|
|
290
|
-
|
|
291
|
-
function scanPatternExpressions(pattern, scope) {
|
|
292
|
-
if (pattern == null) return
|
|
293
|
-
if (pattern.type === 'AssignmentPattern') {
|
|
294
|
-
scanPatternExpressions(pattern.left, scope)
|
|
295
|
-
scan(pattern.right, scope)
|
|
296
|
-
} else if (pattern.type === 'RestElement') {
|
|
297
|
-
scanPatternExpressions(pattern.argument, scope)
|
|
298
|
-
} else if (pattern.type === 'ArrayPattern') {
|
|
299
|
-
for (const element of pattern.elements) scanPatternExpressions(element, scope)
|
|
300
|
-
} else if (pattern.type === 'ObjectPattern') {
|
|
301
|
-
for (const property of pattern.properties) {
|
|
302
|
-
if (property.type === 'RestElement') scanPatternExpressions(property.argument, scope)
|
|
303
|
-
else {
|
|
304
|
-
if (property.computed) scan(property.key, scope)
|
|
305
|
-
scanPatternExpressions(property.value, scope)
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
function scanFunction(node, outerScope) {
|
|
312
|
-
const parameterScope = newScope(outerScope, true)
|
|
313
|
-
scopeAt.set(node, parameterScope)
|
|
314
|
-
if (node.type !== 'ArrowFunctionExpression') parameterScope.bindings.add('arguments')
|
|
315
|
-
if (node.type === 'FunctionExpression' && node.id != null) parameterScope.bindings.add(node.id.name)
|
|
316
|
-
for (const parameter of node.params) declarePattern(parameter, parameterScope)
|
|
317
|
-
for (const parameter of node.params) scanPatternExpressions(parameter, parameterScope)
|
|
318
|
-
if (node.body.type === 'BlockStatement') {
|
|
319
|
-
const bodyScope = newScope(parameterScope, true)
|
|
320
|
-
scopeAt.set(node.body, bodyScope)
|
|
321
|
-
for (const statement of node.body.body) scan(statement, bodyScope)
|
|
322
|
-
} else {
|
|
323
|
-
scan(node.body, parameterScope)
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
function scanClass(node, outerScope) {
|
|
328
|
-
if (node.type === 'ClassDeclaration' && node.id != null) outerScope.bindings.add(node.id.name)
|
|
329
|
-
if (node.superClass != null) scan(node.superClass, outerScope)
|
|
330
|
-
const scope = newScope(outerScope)
|
|
331
|
-
scopeAt.set(node, scope)
|
|
332
|
-
scopeAt.set(node.body, scope)
|
|
333
|
-
if (node.id != null) scope.bindings.add(node.id.name)
|
|
334
|
-
for (const element of node.body.body) scan(element, scope)
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
function scan(node, scope) {
|
|
338
|
-
if (node == null) return
|
|
339
|
-
scopeAt.set(node, scope)
|
|
340
|
-
if (node.type === 'Program') {
|
|
341
|
-
scopeAt.set(node, root)
|
|
342
|
-
for (const statement of node.body) scan(statement, root)
|
|
343
|
-
return
|
|
344
|
-
}
|
|
345
|
-
if (node.type === 'BlockStatement') {
|
|
346
|
-
const block = newScope(scope)
|
|
347
|
-
scopeAt.set(node, block)
|
|
348
|
-
for (const statement of node.body) scan(statement, block)
|
|
349
|
-
return
|
|
350
|
-
}
|
|
351
|
-
if (node.type === 'StaticBlock') {
|
|
352
|
-
const block = newScope(scope, true)
|
|
353
|
-
scopeAt.set(node, block)
|
|
354
|
-
for (const statement of node.body) scan(statement, block)
|
|
355
|
-
return
|
|
356
|
-
}
|
|
357
|
-
if (node.type === 'FunctionDeclaration') {
|
|
358
|
-
if (node.id != null) scope.bindings.add(node.id.name)
|
|
359
|
-
scanFunction(node, scope)
|
|
360
|
-
return
|
|
361
|
-
}
|
|
362
|
-
if (node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') {
|
|
363
|
-
scanFunction(node, scope)
|
|
364
|
-
return
|
|
365
|
-
}
|
|
366
|
-
if (node.type === 'VariableDeclaration') {
|
|
367
|
-
for (const declaration of node.declarations) {
|
|
368
|
-
const bindingScope = node.kind === 'var' ? scope.varScope : scope
|
|
369
|
-
declarePattern(declaration.id, bindingScope)
|
|
370
|
-
scanPatternExpressions(declaration.id, scope)
|
|
371
|
-
if (declaration.init != null) scan(declaration.init, scope)
|
|
372
|
-
}
|
|
373
|
-
return
|
|
374
|
-
}
|
|
375
|
-
if (node.type === 'CatchClause') {
|
|
376
|
-
const catchScope = newScope(scope)
|
|
377
|
-
scopeAt.set(node, catchScope)
|
|
378
|
-
declarePattern(node.param, catchScope)
|
|
379
|
-
scanPatternExpressions(node.param, catchScope)
|
|
380
|
-
scopeAt.set(node.body, catchScope)
|
|
381
|
-
for (const statement of node.body.body) scan(statement, catchScope)
|
|
382
|
-
return
|
|
383
|
-
}
|
|
384
|
-
if (node.type === 'ClassDeclaration' || node.type === 'ClassExpression') {
|
|
385
|
-
scanClass(node, scope)
|
|
386
|
-
return
|
|
387
|
-
}
|
|
388
|
-
if (node.type === 'ForStatement' || node.type === 'ForInStatement' || node.type === 'ForOfStatement') {
|
|
389
|
-
const loopScope = newScope(scope)
|
|
390
|
-
scopeAt.set(node, loopScope)
|
|
391
|
-
for (const [, child] of childEntries(node)) scan(child, loopScope)
|
|
392
|
-
return
|
|
393
|
-
}
|
|
394
|
-
if (node.type === 'SwitchStatement') {
|
|
395
|
-
const switchScope = newScope(scope)
|
|
396
|
-
scopeAt.set(node, switchScope)
|
|
397
|
-
scan(node.discriminant, switchScope)
|
|
398
|
-
for (const switchCase of node.cases) scan(switchCase, switchScope)
|
|
399
|
-
return
|
|
400
|
-
}
|
|
401
|
-
for (const [, child] of childEntries(node)) scan(child, scope)
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
scan(ast, root)
|
|
405
|
-
return scopeAt
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
function isBound(scope, name) {
|
|
409
|
-
for (let current = scope; current != null; current = current.parent) {
|
|
410
|
-
if (current.bindings.has(name)) return true
|
|
411
|
-
}
|
|
412
|
-
return false
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
function visitBindingPatternExpressions(pattern, scope, visit) {
|
|
416
|
-
if (pattern == null) return
|
|
417
|
-
if (pattern.type === 'AssignmentPattern') {
|
|
418
|
-
visitBindingPatternExpressions(pattern.left, scope, visit)
|
|
419
|
-
visit(pattern.right, scope)
|
|
420
|
-
} else if (pattern.type === 'RestElement') {
|
|
421
|
-
visitBindingPatternExpressions(pattern.argument, scope, visit)
|
|
422
|
-
} else if (pattern.type === 'ArrayPattern') {
|
|
423
|
-
for (const element of pattern.elements) visitBindingPatternExpressions(element, scope, visit)
|
|
424
|
-
} else if (pattern.type === 'ObjectPattern') {
|
|
425
|
-
for (const property of pattern.properties) {
|
|
426
|
-
if (property.type === 'RestElement') visitBindingPatternExpressions(property.argument, scope, visit)
|
|
427
|
-
else {
|
|
428
|
-
if (property.computed) visit(property.key, scope)
|
|
429
|
-
visitBindingPatternExpressions(property.value, scope, visit)
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
function validateUnresolvedReferences(ast) {
|
|
436
|
-
const scopeAt = buildScopeModel(ast)
|
|
437
|
-
|
|
438
|
-
function validateIdentifier(node, scope) {
|
|
439
|
-
if (isBound(scope, node.name) || ALLOWED_GLOBALS.has(node.name)) return
|
|
440
|
-
fail(FORBIDDEN_CAPABILITY)
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
function visitAssignmentTarget(node, scope) {
|
|
444
|
-
if (node.type === 'Identifier') {
|
|
445
|
-
validateIdentifier(node, scope)
|
|
446
|
-
} else if (node.type === 'MemberExpression') {
|
|
447
|
-
visit(node.object, scope)
|
|
448
|
-
if (node.computed) visit(node.property, scope)
|
|
449
|
-
} else if (node.type === 'RestElement') {
|
|
450
|
-
visitAssignmentTarget(node.argument, scope)
|
|
451
|
-
} else if (node.type === 'AssignmentPattern') {
|
|
452
|
-
visitAssignmentTarget(node.left, scope)
|
|
453
|
-
visit(node.right, scope)
|
|
454
|
-
} else if (node.type === 'ArrayPattern') {
|
|
455
|
-
for (const element of node.elements) if (element != null) visitAssignmentTarget(element, scope)
|
|
456
|
-
} else if (node.type === 'ObjectPattern') {
|
|
457
|
-
for (const property of node.properties) {
|
|
458
|
-
if (property.type === 'RestElement') visitAssignmentTarget(property.argument, scope)
|
|
459
|
-
else {
|
|
460
|
-
if (property.computed) visit(property.key, scope)
|
|
461
|
-
visitAssignmentTarget(property.value, scope)
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
function visitFunction(node) {
|
|
468
|
-
const scope = scopeAt.get(node)
|
|
469
|
-
for (const parameter of node.params) visitBindingPatternExpressions(parameter, scope, visit)
|
|
470
|
-
visit(node.body, scope)
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
function visitClass(node, outerScope) {
|
|
474
|
-
if (node.superClass != null) visit(node.superClass, outerScope)
|
|
475
|
-
visit(node.body, scopeAt.get(node))
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
function visit(node, inheritedScope, parent = null) {
|
|
479
|
-
if (node == null) return
|
|
480
|
-
const scope = scopeAt.get(node) ?? inheritedScope
|
|
481
|
-
if (node.type === 'Identifier') {
|
|
482
|
-
validateIdentifier(node, scope)
|
|
483
|
-
return
|
|
484
|
-
}
|
|
485
|
-
if (node.type === 'VariableDeclaration') {
|
|
486
|
-
for (const declaration of node.declarations) {
|
|
487
|
-
visitBindingPatternExpressions(declaration.id, scope, visit)
|
|
488
|
-
if (declaration.init != null) visit(declaration.init, scope, declaration)
|
|
489
|
-
}
|
|
490
|
-
return
|
|
491
|
-
}
|
|
492
|
-
if (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression'
|
|
493
|
-
|| node.type === 'ArrowFunctionExpression') {
|
|
494
|
-
visitFunction(node)
|
|
495
|
-
return
|
|
496
|
-
}
|
|
497
|
-
if (node.type === 'ClassDeclaration' || node.type === 'ClassExpression') {
|
|
498
|
-
visitClass(node, inheritedScope)
|
|
499
|
-
return
|
|
500
|
-
}
|
|
501
|
-
if (node.type === 'CatchClause') {
|
|
502
|
-
visitBindingPatternExpressions(node.param, scope, visit)
|
|
503
|
-
visit(node.body, scope, node)
|
|
504
|
-
return
|
|
505
|
-
}
|
|
506
|
-
if (node.type === 'MemberExpression') {
|
|
507
|
-
visit(node.object, scope, node)
|
|
508
|
-
if (node.computed) visit(node.property, scope, node)
|
|
509
|
-
return
|
|
510
|
-
}
|
|
511
|
-
if (node.type === 'Property') {
|
|
512
|
-
if (node.computed) visit(node.key, scope, node)
|
|
513
|
-
visit(node.value, scope, node)
|
|
514
|
-
return
|
|
515
|
-
}
|
|
516
|
-
if (node.type === 'MethodDefinition' || node.type === 'PropertyDefinition') {
|
|
517
|
-
if (node.computed) visit(node.key, scope, node)
|
|
518
|
-
if (node.value != null) visit(node.value, scope, node)
|
|
519
|
-
return
|
|
520
|
-
}
|
|
521
|
-
if (node.type === 'AssignmentExpression') {
|
|
522
|
-
visitAssignmentTarget(node.left, scope)
|
|
523
|
-
visit(node.right, scope, node)
|
|
524
|
-
return
|
|
525
|
-
}
|
|
526
|
-
if (node.type === 'UpdateExpression') {
|
|
527
|
-
visitAssignmentTarget(node.argument, scope)
|
|
528
|
-
return
|
|
529
|
-
}
|
|
530
|
-
if (node.type === 'LabeledStatement') {
|
|
531
|
-
visit(node.body, scope, node)
|
|
532
|
-
return
|
|
533
|
-
}
|
|
534
|
-
if (node.type === 'BreakStatement' || node.type === 'ContinueStatement'
|
|
535
|
-
|| node.type === 'PrivateIdentifier' || node.type === 'MetaProperty') return
|
|
536
|
-
if (node.type === 'ExportSpecifier') {
|
|
537
|
-
visit(node.local, scope, node)
|
|
538
|
-
return
|
|
539
|
-
}
|
|
540
|
-
if (node.type === 'ImportSpecifier' || node.type === 'ImportDefaultSpecifier'
|
|
541
|
-
|| node.type === 'ImportNamespaceSpecifier') return
|
|
542
|
-
for (const [, child] of childEntries(node)) visit(child, scope, node)
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
visit(ast, scopeAt.get(ast))
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
function validateCapabilityNode(node, parent) {
|
|
549
|
-
if ((node.type === 'MemberExpression' || node.type === 'Property'
|
|
550
|
-
|| node.type === 'MethodDefinition' || node.type === 'PropertyDefinition') && node.computed) {
|
|
551
|
-
fail(FORBIDDEN_CAPABILITY)
|
|
552
|
-
}
|
|
553
|
-
if ((node.type === 'MemberExpression' || node.type === 'Property'
|
|
554
|
-
|| node.type === 'MethodDefinition' || node.type === 'PropertyDefinition')
|
|
555
|
-
&& FORBIDDEN_PROPERTIES.has(staticPropertyName(node.type === 'MemberExpression' ? node.property : node.key))) {
|
|
556
|
-
fail(FORBIDDEN_CAPABILITY)
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
function validateAdapterPolicy(source) {
|
|
561
|
-
let ast
|
|
562
|
-
try {
|
|
563
|
-
ast = parse(source, { ecmaVersion: 'latest', sourceType: 'module' })
|
|
564
|
-
} catch {
|
|
565
|
-
fail('e:adapter-invalid-syntax')
|
|
566
|
-
}
|
|
567
|
-
const pending = [{ node: ast, parent: null }]
|
|
568
|
-
while (pending.length > 0) {
|
|
569
|
-
const { node, parent } = pending.pop()
|
|
570
|
-
if (node.type === 'ImportDeclaration'
|
|
571
|
-
|| node.type === 'ImportExpression'
|
|
572
|
-
|| node.type === 'ExportAllDeclaration'
|
|
573
|
-
|| (node.type === 'ExportNamedDeclaration' && node.source != null)
|
|
574
|
-
|| (node.type === 'MetaProperty' && node.meta?.name === 'import')) {
|
|
575
|
-
fail(FORBIDDEN_DEPENDENCY)
|
|
576
|
-
}
|
|
577
|
-
validateCapabilityNode(node, parent)
|
|
578
|
-
pending.push(...children(node).map((child) => ({ node: child, parent: node })))
|
|
579
|
-
}
|
|
580
|
-
validateUnresolvedReferences(ast)
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
async function executeBytes(bytes, source, contentHash) {
|
|
584
|
-
let cached = MODULE_CACHE.get(contentHash)
|
|
585
|
-
if (cached == null) {
|
|
586
|
-
const boundBytes = Buffer.from(bytes)
|
|
587
|
-
cached = inspectIsolatedAdapter({ source, bytes: boundBytes, contentHash })
|
|
588
|
-
.then(({ module }) => module)
|
|
589
|
-
.catch((error) => {
|
|
590
|
-
MODULE_CACHE.delete(contentHash)
|
|
591
|
-
if (typeof error?.code === 'string' && error.code.startsWith('e:adapter-')) fail(error.code)
|
|
592
|
-
fail('e:adapter-execution-failed')
|
|
593
|
-
})
|
|
594
|
-
MODULE_CACHE.set(contentHash, cached)
|
|
595
|
-
}
|
|
596
|
-
try {
|
|
597
|
-
return await cached
|
|
598
|
-
} catch (error) {
|
|
599
|
-
if (error instanceof CheckedAdapterError) throw error
|
|
600
|
-
fail('e:adapter-execution-failed')
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
export async function loadCheckedAdapter({ repositoryRoot, adapterPath, onFilesystemBoundary } = {}) {
|
|
605
|
-
const acquired = acquireSource(repositoryRoot, adapterPath, onFilesystemBoundary)
|
|
606
|
-
const source = decodeStrictUtf8(acquired.bytes)
|
|
607
|
-
validateAdapterPolicy(source)
|
|
608
|
-
const contentHash = crypto.createHash('sha256').update(acquired.bytes).digest('hex')
|
|
609
|
-
notifyFilesystemBoundary(onFilesystemBoundary, 'after-acquire')
|
|
610
|
-
const module = await executeBytes(acquired.bytes, source, contentHash)
|
|
611
|
-
return Object.freeze({ module, canonicalPath: acquired.canonicalPath, contentHash })
|
|
612
|
-
}
|