@ai-ecoverse/slicc-browsers 1.18.12 → 1.18.14

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.
@@ -9,6 +9,28 @@ const marker =
9
9
  'typeof root !== "undefined" && root === document.documentElement && root.dataset.sliccHarnessExtension === chrome.runtime.id';
10
10
  const refused = (out) => !out.ok && /^slicc: refused:/.test(out.error?.message ?? '');
11
11
 
12
+ async function painted(reader, observer, ms) {
13
+ let timer;
14
+ const expired = new Promise((resolve) => {
15
+ timer = setTimeout(resolve, ms);
16
+ });
17
+ await Promise.race([
18
+ outcome(
19
+ reader.send(
20
+ 'Runtime.evaluate',
21
+ {
22
+ expression: `new Promise((resolve) => { setTimeout(resolve, ${ms}); requestAnimationFrame(() => requestAnimationFrame(resolve)); })`,
23
+ awaitPromise: true,
24
+ returnByValue: true,
25
+ },
26
+ observer
27
+ )
28
+ ),
29
+ expired,
30
+ ]);
31
+ clearTimeout(timer);
32
+ }
33
+
12
34
  async function discover(reader, session, extensionId) {
13
35
  const start = reader.events.length;
14
36
  await reader.send('Runtime.enable', {}, session);
@@ -29,7 +51,7 @@ async function discover(reader, session, extensionId) {
29
51
  throw new Error(`extensionWorld: no content-script context for ${extensionId}`);
30
52
  }
31
53
 
32
- async function drivable({ client, session, live, reader, observer }) {
54
+ async function drivable({ client, session, live, reader, observer, frameMs }) {
33
55
  const setup = await outcome(
34
56
  client.send(
35
57
  'Runtime.evaluate',
@@ -45,6 +67,7 @@ async function drivable({ client, session, live, reader, observer }) {
45
67
  client.send('DOMSnapshot.captureSnapshot', { computedStyles: [] }, session)
46
68
  );
47
69
  await outcome(reader.send('Page.bringToFront', {}, observer));
70
+ await painted(reader, observer, frameMs);
48
71
  const down = await outcome(
49
72
  client.send(
50
73
  'Input.dispatchMouseEvent',
@@ -324,6 +347,7 @@ export async function extensionWorld({
324
347
  controls,
325
348
  extensionId = DEFAULT_EXTENSION_WORLD_ID,
326
349
  pauseMs = side === 'control' ? 5000 : 1500,
350
+ frameMs = 1000,
327
351
  }) {
328
352
  const attached = await reader.send('Target.attachToTarget', { targetId, flatten: true });
329
353
  const observer = attached.sessionId;
@@ -395,6 +419,7 @@ export async function extensionWorld({
395
419
  side,
396
420
  controls,
397
421
  pauseMs,
422
+ frameMs,
398
423
  };
399
424
  if (mode === 'drivable') return await drivable(input);
400
425
  if (mode === 'debugger') return await debuggerWorld(input);
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
- if (await check()) return true;
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);
@@ -846,6 +854,7 @@ class Execution {
846
854
  side: this.side,
847
855
  controls: (this.clients.extensionWorldControls ??= {}),
848
856
  pauseMs: this.bound(this.side === 'control' ? 5000 : 1500, this.side !== 'control'),
857
+ frameMs: this.bound(1000),
849
858
  extensionId: this.options.extensionWorldId,
850
859
  })
851
860
  );
@@ -1069,12 +1078,42 @@ class Execution {
1069
1078
  (at(this.calls[check.result], check.path) === 'incomplete' || this.unmeasured(check))
1070
1079
  )
1071
1080
  return 'incomplete';
1072
- if (want !== true || check?.observer !== 'fixture') return this.check(check);
1081
+ const plan = steps(this.vector, this.side, this.vars);
1082
+ const names = resultNames(check);
1083
+ const snapshots =
1084
+ this.side === 'control' && want === true && !this.clients.flight?.abandoned
1085
+ ? [...plan.setup, ...plan.trigger].filter(
1086
+ (step) =>
1087
+ names.includes(step.as) &&
1088
+ !step.refusable &&
1089
+ ['Page.getFrameTree', 'Target.getTargets'].includes(step.cdp) &&
1090
+ supported(step.requires, this.options.capabilities)
1091
+ )
1092
+ : [];
1093
+ if (want !== true || (check?.observer !== 'fixture' && !snapshots.length))
1094
+ return this.check(check);
1073
1095
  let seen = false;
1074
- await this.poll(async () => {
1075
- seen = await this.check(check);
1076
- return seen === true;
1077
- }, observeMs);
1096
+ const met = await this.poll(
1097
+ async () => {
1098
+ if (this.clients.flight?.abandoned) return true;
1099
+ seen = await this.check(check);
1100
+ if (seen !== true && snapshots.length) {
1101
+ await this.execute(snapshots, undefined, 'observation');
1102
+ if (this.clients.flight?.abandoned) return true;
1103
+ seen = await this.check(check);
1104
+ }
1105
+ return seen === true;
1106
+ },
1107
+ observeMs,
1108
+ false,
1109
+ snapshots.length > 0
1110
+ );
1111
+ if ((!met || this.clients.flight?.abandoned) && snapshots.length) {
1112
+ this.incomplete.push(
1113
+ `${name}: snapshot evidence not observed within ${this.bound(observeMs)}ms`
1114
+ );
1115
+ return 'incomplete';
1116
+ }
1078
1117
  return seen;
1079
1118
  }
1080
1119
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "setVersion": "1.18.12",
3
+ "setVersion": "1.18.14",
4
4
  "sources": [
5
5
  {
6
6
  "repo": "ai-ecoverse/slicc-cli",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc-browsers",
3
- "version": "1.18.12",
3
+ "version": "1.18.14",
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/guard-world-paint.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.33.1",
83
- "@ai-ecoverse/slicc-shared-web": "2.11.0",
82
+ "@ai-ecoverse/slicc-cdp": "1.41.8",
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",