@ai-ecoverse/slicc-browsers 1.18.11 → 1.18.13
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 +2 -0
- package/guard-driver.mjs +11 -2
- package/guard-runner.mjs +45 -7
- package/guard-vectors.json +1 -1
- package/package.json +5 -5
- package/protected-error-page.mjs +3 -4
package/README.md
CHANGED
|
@@ -186,6 +186,8 @@ Each vector runs twice. The **control** runs it against an ordinary origin, wher
|
|
|
186
186
|
|
|
187
187
|
When a vector compares ordinary and protected fixture markers, those markers do not contain one another. Protected-marker checks still examine complete probe replies, including errors, and the vector's client events and messages, including encoded values.
|
|
188
188
|
|
|
189
|
+
A guard may refuse every client navigation to an `about:` URL that inherits an origin, such as `about:blank`. Refusing an ordinary navigation away from a protected page still fails.
|
|
190
|
+
|
|
189
191
|
Client-exit controls use the unguarded observer; persistent-capability refusals are valid evidence, granted instruments must leave no effects after exit, and missing answers remain incomplete.
|
|
190
192
|
|
|
191
193
|
Forwarding audits retain early snapshots as evidence. A complete final ledger supersedes an incomplete early snapshot, but any forwarding reported in either audit remains a failure. An incomplete final audit remains missing evidence.
|
package/guard-driver.mjs
CHANGED
|
@@ -135,7 +135,7 @@ export async function load(client, sessionId, url, ms = 20000) {
|
|
|
135
135
|
throw new Error(`load of ${url} timed out`);
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
export async function waitFor(check, ms, step = 25) {
|
|
138
|
+
export async function waitFor(check, ms, step = 25, bounded = false) {
|
|
139
139
|
const start = Date.now();
|
|
140
140
|
const limit = start + ms + Math.max(ms * 4, 30000);
|
|
141
141
|
let deadline = start + ms;
|
|
@@ -147,14 +147,23 @@ export async function waitFor(check, ms, step = 25) {
|
|
|
147
147
|
last = now;
|
|
148
148
|
};
|
|
149
149
|
let timer;
|
|
150
|
+
let expire;
|
|
150
151
|
const tick = () => {
|
|
151
152
|
beat();
|
|
153
|
+
if (Date.now() > deadline) expire?.();
|
|
152
154
|
timer = setTimeout(tick, step);
|
|
153
155
|
};
|
|
154
156
|
timer = setTimeout(tick, step);
|
|
155
157
|
try {
|
|
156
158
|
for (;;) {
|
|
157
|
-
|
|
159
|
+
const expired = bounded
|
|
160
|
+
? new Promise((resolve) => {
|
|
161
|
+
expire = () => resolve(false);
|
|
162
|
+
})
|
|
163
|
+
: undefined;
|
|
164
|
+
const met = bounded ? await Promise.race([check(), expired]) : await check();
|
|
165
|
+
expire = undefined;
|
|
166
|
+
if (met) return true;
|
|
158
167
|
beat();
|
|
159
168
|
if (Date.now() > deadline) return false;
|
|
160
169
|
await new Promise((resolve) => setTimeout(resolve, step));
|
package/guard-runner.mjs
CHANGED
|
@@ -70,6 +70,13 @@ const observedValue = (out, path) => {
|
|
|
70
70
|
|
|
71
71
|
const address = (value) =>
|
|
72
72
|
typeof value === 'string' ? value : hop(value.hops.slice(value.index ?? 0), value.to);
|
|
73
|
+
const resultNames = (check) =>
|
|
74
|
+
[
|
|
75
|
+
check?.result,
|
|
76
|
+
...[...(check?.all ?? []), ...(check?.any ?? []), ...(check?.not ? [check.not] : [])].flatMap(
|
|
77
|
+
resultNames
|
|
78
|
+
),
|
|
79
|
+
].filter(Boolean);
|
|
73
80
|
const stateCheck = (check) =>
|
|
74
81
|
check?.state ||
|
|
75
82
|
[...(check?.all ?? []), ...(check?.any ?? []), ...(check?.not ? [check.not] : [])]
|
|
@@ -235,8 +242,8 @@ class Execution {
|
|
|
235
242
|
return Math.round(ms * (absent ? this.refusalScale : this.scale));
|
|
236
243
|
}
|
|
237
244
|
|
|
238
|
-
async poll(predicate, ms = 1500, absent = false) {
|
|
239
|
-
return waitFor(predicate, this.bound(ms, absent));
|
|
245
|
+
async poll(predicate, ms = 1500, absent = false, bounded = false) {
|
|
246
|
+
return waitFor(predicate, this.bound(ms, absent), 25, bounded);
|
|
240
247
|
}
|
|
241
248
|
|
|
242
249
|
async prepareState(spec) {
|
|
@@ -705,6 +712,7 @@ class Execution {
|
|
|
705
712
|
async execute(list, childSession, phase = 'child') {
|
|
706
713
|
if (phase === 'trigger') await this.childrenSettled();
|
|
707
714
|
for (const [index, raw] of list.entries()) {
|
|
715
|
+
if (phase === 'observation' && this.clients.flight?.abandoned) return;
|
|
708
716
|
if (this.clients.flight)
|
|
709
717
|
Object.assign(this.clients.flight, { leg: this.side, phase, step: index });
|
|
710
718
|
const step = expand(raw, this.vars);
|
|
@@ -1069,12 +1077,42 @@ class Execution {
|
|
|
1069
1077
|
(at(this.calls[check.result], check.path) === 'incomplete' || this.unmeasured(check))
|
|
1070
1078
|
)
|
|
1071
1079
|
return 'incomplete';
|
|
1072
|
-
|
|
1080
|
+
const plan = steps(this.vector, this.side, this.vars);
|
|
1081
|
+
const names = resultNames(check);
|
|
1082
|
+
const snapshots =
|
|
1083
|
+
this.side === 'control' && want === true && !this.clients.flight?.abandoned
|
|
1084
|
+
? [...plan.setup, ...plan.trigger].filter(
|
|
1085
|
+
(step) =>
|
|
1086
|
+
names.includes(step.as) &&
|
|
1087
|
+
!step.refusable &&
|
|
1088
|
+
['Page.getFrameTree', 'Target.getTargets'].includes(step.cdp) &&
|
|
1089
|
+
supported(step.requires, this.options.capabilities)
|
|
1090
|
+
)
|
|
1091
|
+
: [];
|
|
1092
|
+
if (want !== true || (check?.observer !== 'fixture' && !snapshots.length))
|
|
1093
|
+
return this.check(check);
|
|
1073
1094
|
let seen = false;
|
|
1074
|
-
await this.poll(
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1095
|
+
const met = await this.poll(
|
|
1096
|
+
async () => {
|
|
1097
|
+
if (this.clients.flight?.abandoned) return true;
|
|
1098
|
+
seen = await this.check(check);
|
|
1099
|
+
if (seen !== true && snapshots.length) {
|
|
1100
|
+
await this.execute(snapshots, undefined, 'observation');
|
|
1101
|
+
if (this.clients.flight?.abandoned) return true;
|
|
1102
|
+
seen = await this.check(check);
|
|
1103
|
+
}
|
|
1104
|
+
return seen === true;
|
|
1105
|
+
},
|
|
1106
|
+
observeMs,
|
|
1107
|
+
false,
|
|
1108
|
+
snapshots.length > 0
|
|
1109
|
+
);
|
|
1110
|
+
if ((!met || this.clients.flight?.abandoned) && snapshots.length) {
|
|
1111
|
+
this.incomplete.push(
|
|
1112
|
+
`${name}: snapshot evidence not observed within ${this.bound(observeMs)}ms`
|
|
1113
|
+
);
|
|
1114
|
+
return 'incomplete';
|
|
1115
|
+
}
|
|
1078
1116
|
return seen;
|
|
1079
1117
|
}
|
|
1080
1118
|
|
package/guard-vectors.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc-browsers",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.13",
|
|
4
4
|
"description": "SLICC's shared browser catalog, JSON schemas and discovery conformance corpus",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"validate": "node scripts/validate.mjs",
|
|
69
69
|
"lint": "slicc-lint && test -z \"$(gofmt -l .)\" && go mod tidy -diff && go vet ./... && GOOS=darwin go vet ./... && GOOS=windows go vet ./... && golangci-lint run && cargo fmt --check && cargo clippy --all-features --all-targets -- -D warnings && cargo check --target wasm32-wasip1 --no-default-features && cargo check --target wasm32-wasip1 --features serde && cargo check --target wasm32-wasip1 --all-features",
|
|
70
70
|
"format": "biome check --write . && gofmt -w . && cargo fmt",
|
|
71
|
-
"test": "export PATH=\"$HOME/.cargo/bin:$PATH\" && node --test --test-concurrency=1 test/integration/self-contained.test.mjs test/integration/browser-runner.test.mjs test/integration/fixture-client.test.mjs test/integration/guard-redirect-carrier.test.mjs test/integration/guard-redirect-session-end.test.mjs test/integration/guard-redirect-history.test.mjs test/integration/guard-redirect-iframe.test.mjs test/integration/guard-incomplete.test.mjs test/integration/guard-stall.test.mjs test/integration/guard-forged.test.mjs test/integration/guard-exit-steps.test.mjs test/integration/guard-exit-refusal.test.mjs test/integration/guard-frame-read.test.mjs test/integration/guard-bfcache.test.mjs test/integration/guard-bfcache-marker.test.mjs test/integration/guard-bfcache-history.test.mjs test/integration/guard-bfcache-review.test.mjs test/integration/guard-bfcache-quarantine.test.mjs test/integration/guard-error-page-navigation.test.mjs test/integration/gates.test.mjs test/integration/validate.test.mjs test/integration/go.test.mjs test/integration/cargo.test.mjs test/integration/workflows.test.mjs test/integration/guard-sweep-union.test.mjs && node --test --test-concurrency=2 test/integration/guard-lifecycle.test.mjs test/integration/guard-fit.test.mjs test/integration/guard-chain.test.mjs test/integration/guard-validation.test.mjs test/integration/guard-liveness.test.mjs test/integration/guard-observations.test.mjs test/integration/guard-child-latency.test.mjs test/integration/guard-adoption.test.mjs test/integration/guard-scoping.test.mjs test/integration/guard-late-pause.test.mjs test/integration/guard-legs.test.mjs test/integration/guard-fetch-enable.test.mjs test/integration/guard-diagnostics.test.mjs test/integration/guard-chrome.test.mjs test/integration/guard-worlds.test.mjs test/integration/guard-world-discovery.test.mjs test/integration/guard-world-guesses.test.mjs test/integration/guard-unparseable.test.mjs test/integration/guard-redirect-secret.test.mjs test/integration/guard-error-page.test.mjs test/integration/guard-discovery.test.mjs test/integration/guard-bfcache-chrome.test.mjs test/integration/guard-browser-page.test.mjs test/integration/guard-scales.test.mjs test/integration/guard-shared-log.test.mjs test/integration/guard-pre-beacon.test.mjs test/integration/guard-world-pause.test.mjs test/integration/guard-parallel.test.mjs test/integration/guard-client-exit.test.mjs test/integration/guard-runner.test.mjs test/integration/guard-sweep-ordinary.test.mjs test/integration/guard-sweep-seven.test.mjs test/integration/guard-sweep-vault.test.mjs test/integration/guard-sweep-vault-x.test.mjs test/integration/guard-sweep-apex.test.mjs test/integration/guard-sweep-others.test.mjs",
|
|
71
|
+
"test": "export PATH=\"$HOME/.cargo/bin:$PATH\" && node --test --test-concurrency=1 test/integration/self-contained.test.mjs test/integration/browser-runner.test.mjs test/integration/fixture-client.test.mjs test/integration/guard-redirect-carrier.test.mjs test/integration/guard-redirect-session-end.test.mjs test/integration/guard-redirect-history.test.mjs test/integration/guard-redirect-iframe.test.mjs test/integration/guard-incomplete.test.mjs test/integration/guard-snapshot-settle.test.mjs test/integration/guard-stall.test.mjs test/integration/guard-forged.test.mjs test/integration/guard-exit-steps.test.mjs test/integration/guard-exit-refusal.test.mjs test/integration/guard-frame-read.test.mjs test/integration/guard-bfcache.test.mjs test/integration/guard-bfcache-marker.test.mjs test/integration/guard-bfcache-history.test.mjs test/integration/guard-bfcache-review.test.mjs test/integration/guard-bfcache-quarantine.test.mjs test/integration/guard-error-page-navigation.test.mjs test/integration/gates.test.mjs test/integration/validate.test.mjs test/integration/go.test.mjs test/integration/cargo.test.mjs test/integration/workflows.test.mjs test/integration/guard-sweep-union.test.mjs && node --test --test-concurrency=2 test/integration/guard-lifecycle.test.mjs test/integration/guard-fit.test.mjs test/integration/guard-chain.test.mjs test/integration/guard-validation.test.mjs test/integration/guard-liveness.test.mjs test/integration/guard-observations.test.mjs test/integration/guard-child-latency.test.mjs test/integration/guard-adoption.test.mjs test/integration/guard-scoping.test.mjs test/integration/guard-late-pause.test.mjs test/integration/guard-legs.test.mjs test/integration/guard-fetch-enable.test.mjs test/integration/guard-diagnostics.test.mjs test/integration/guard-chrome.test.mjs test/integration/guard-worlds.test.mjs test/integration/guard-world-discovery.test.mjs test/integration/guard-world-guesses.test.mjs test/integration/guard-unparseable.test.mjs test/integration/guard-redirect-secret.test.mjs test/integration/guard-error-page.test.mjs test/integration/guard-discovery.test.mjs test/integration/guard-bfcache-chrome.test.mjs test/integration/guard-browser-page.test.mjs test/integration/guard-scales.test.mjs test/integration/guard-shared-log.test.mjs test/integration/guard-pre-beacon.test.mjs test/integration/guard-world-pause.test.mjs test/integration/guard-parallel.test.mjs test/integration/guard-client-exit.test.mjs test/integration/guard-runner.test.mjs test/integration/guard-sweep-ordinary.test.mjs test/integration/guard-sweep-seven.test.mjs test/integration/guard-sweep-vault.test.mjs test/integration/guard-sweep-vault-x.test.mjs test/integration/guard-sweep-apex.test.mjs test/integration/guard-sweep-others.test.mjs",
|
|
72
72
|
"test:unit": "mkdir -p coverage/unit && node --experimental-test-coverage --test --test-concurrency=1 --test-reporter=lcov --test-reporter-destination=coverage/unit/lcov.info test/unit/*.test.mjs && go test -race -cover ./...",
|
|
73
73
|
"build": "go build ./... && cargo build --all-features && cargo build --target wasm32-wasip1 --all-features && npm pack --dry-run",
|
|
74
74
|
"prepublishOnly": "node scripts/set-crate-version.mjs \"$npm_package_version\"",
|
|
@@ -76,11 +76,11 @@
|
|
|
76
76
|
"trust:dry": "npx fledgling sync --dry-run -y --skip-publish",
|
|
77
77
|
"release": "semantic-release",
|
|
78
78
|
"test:unit:redirect": "mkdir -p coverage/unit && node --experimental-test-coverage --test --test-concurrency=1 --test-coverage-include=redirect-secret.mjs --test-coverage-include=redirect-fragments.mjs --test-reporter=lcov --test-reporter-destination=coverage/unit/redirect.lcov test/unit/guard-redirect-*.test.mjs && slicc-diff-cover coverage/unit/redirect.lcov",
|
|
79
|
-
"test:unit:guard": "mkdir -p coverage/unit && node --experimental-vm-modules --no-warnings --experimental-test-coverage --test --test-concurrency=1 --test-coverage-include=guard-runner.mjs --test-coverage-include=fixture-server.mjs --test-coverage-include=fixture-client.mjs --test-coverage-include=observer-target.mjs --test-coverage-include=frame-read.mjs --test-coverage-include=bfcache-restore.mjs --test-coverage-include=protected-error-page.mjs --test-coverage-include=unparseable-url.mjs --test-coverage-include=scripts/browser-runner.mjs --test-coverage-include=scripts/validate.mjs --test-reporter=lcov --test-reporter-destination=coverage/unit/guard.lcov test/unit/guard-*.test.mjs && slicc-diff-cover coverage/unit/guard.lcov"
|
|
79
|
+
"test:unit:guard": "mkdir -p coverage/unit && node --experimental-vm-modules --no-warnings --experimental-test-coverage --test --test-concurrency=1 --test-coverage-include=guard-runner.mjs --test-coverage-include=guard-driver.mjs --test-coverage-include=fixture-server.mjs --test-coverage-include=fixture-client.mjs --test-coverage-include=observer-target.mjs --test-coverage-include=frame-read.mjs --test-coverage-include=bfcache-restore.mjs --test-coverage-include=protected-error-page.mjs --test-coverage-include=unparseable-url.mjs --test-coverage-include=scripts/browser-runner.mjs --test-coverage-include=scripts/validate.mjs --test-reporter=lcov --test-reporter-destination=coverage/unit/guard.lcov test/unit/guard-*.test.mjs && slicc-diff-cover coverage/unit/guard.lcov"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
|
-
"@ai-ecoverse/slicc-cdp": "1.
|
|
83
|
-
"@ai-ecoverse/slicc-shared-web": "2.
|
|
82
|
+
"@ai-ecoverse/slicc-cdp": "1.41.4",
|
|
83
|
+
"@ai-ecoverse/slicc-shared-web": "2.12.1",
|
|
84
84
|
"@biomejs/biome": "2.5.15",
|
|
85
85
|
"ajv": "8.20.0",
|
|
86
86
|
"ajv-formats": "3.0.1",
|
package/protected-error-page.mjs
CHANGED
|
@@ -269,10 +269,9 @@ export async function protectedErrorPage({
|
|
|
269
269
|
});
|
|
270
270
|
result.reload = result.reloadedError;
|
|
271
271
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
).
|
|
275
|
-
if (result.blank) result.blank = await loaded('about:blank');
|
|
272
|
+
const recovery = `${ordinary}/blank?n=${tag}-recover`;
|
|
273
|
+
result.blank = (await outcome(client.send('Page.navigate', { url: recovery }, session))).ok;
|
|
274
|
+
if (result.blank) result.blank = await loaded(recovery);
|
|
276
275
|
result.attached = !client.events
|
|
277
276
|
.slice(start)
|
|
278
277
|
.some((e) => e.method === 'Target.detachedFromTarget' && e.params.sessionId === session);
|