@ai-ecoverse/slicc-browsers 1.18.13 → 1.18.15

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-runner.mjs CHANGED
@@ -32,6 +32,8 @@ import { canonicalURL, unparseableURLs } from './unparseable-url.mjs';
32
32
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
33
33
  const namedResultMs = 10000;
34
34
  const observeMs = 5000;
35
+ const browserUiAttempts = 3;
36
+ const browserUiMs = 5000;
35
37
  const q = JSON.stringify;
36
38
 
37
39
  const at = (value, path = '') =>
@@ -82,6 +84,8 @@ const stateCheck = (check) =>
82
84
  [...(check?.all ?? []), ...(check?.any ?? []), ...(check?.not ? [check.not] : [])]
83
85
  .map(stateCheck)
84
86
  .find(Boolean);
87
+ const refusedOut = (step, out) =>
88
+ step.refusable ? isRefusal(out, step) : /refused/.test(String(out.error?.message ?? out.error));
85
89
 
86
90
  function pageExpression(step, url) {
87
91
  let expression;
@@ -662,11 +666,7 @@ class Execution {
662
666
  }
663
667
 
664
668
  record(step, out, session, phase, gone) {
665
- const refused =
666
- !gone &&
667
- (step.refusable
668
- ? isRefusal(out, step)
669
- : /refused/.test(String(out.error?.message ?? out.error)));
669
+ const refused = !gone && refusedOut(step, out);
670
670
  this.trace.push({
671
671
  phase,
672
672
  declared: Boolean(step.refusable),
@@ -719,8 +719,9 @@ class Execution {
719
719
  if (!supported(step.requires, this.options.capabilities) || step.text) continue;
720
720
  if (!childSession && step.session === 'child') await this.childrenSettled();
721
721
  const session = childSession ?? this.session(step.session);
722
- const out = await this.operation(step, session, phase);
723
- if (!out) continue;
722
+ const first = await this.operation(step, session, phase);
723
+ if (!first) continue;
724
+ const out = await this.browserUiRetry(step, first, session, phase);
724
725
  this.record(
725
726
  step,
726
727
  out,
@@ -732,6 +733,41 @@ class Execution {
732
733
  }
733
734
  }
734
735
 
736
+ async browserUiRetry(step, out, session, phase) {
737
+ const tried = new Set();
738
+ let current = step;
739
+ let last = out;
740
+ for (let attempt = 1; attempt < browserUiAttempts; attempt++) {
741
+ const next = await this.replacementUi(current, last, tried);
742
+ if (!next) break;
743
+ current = { ...current, params: { ...current.params, targetId: next } };
744
+ last = await this.operation(current, session, phase);
745
+ }
746
+ return last;
747
+ }
748
+
749
+ async replacementUi(step, out, tried) {
750
+ const vanished = step.params?.targetId;
751
+ if (out.ok || !vanished || vanished !== this.vars.browserUi || refusedOut(step, out))
752
+ return undefined;
753
+ tried.add(vanished);
754
+ const reader = this.reader ?? this.client;
755
+ let next;
756
+ await this.poll(async () => {
757
+ const listed = await outcome(reader.send('Target.getTargets', {}));
758
+ const infos = listed.ok ? (listed.result?.targetInfos ?? []) : [];
759
+ if (!listed.ok || infos.some((info) => info.targetId === vanished)) return true;
760
+ next = infos.find((info) => info.type === 'browser_ui' && !tried.has(info.targetId));
761
+ return Boolean(next);
762
+ }, browserUiMs);
763
+ if (!next) return undefined;
764
+ this.notes.push(
765
+ `{browserUi} ${vanished} was gone when ${step.cdp} reached it; retried with ${next.targetId}`
766
+ );
767
+ this.vars.browserUi = next.targetId;
768
+ return next.targetId;
769
+ }
770
+
735
771
  async operation(step, session, phase) {
736
772
  if (step.children) {
737
773
  this.childSteps = step.children;
@@ -854,6 +890,7 @@ class Execution {
854
890
  side: this.side,
855
891
  controls: (this.clients.extensionWorldControls ??= {}),
856
892
  pauseMs: this.bound(this.side === 'control' ? 5000 : 1500, this.side !== 'control'),
893
+ frameMs: this.bound(1000),
857
894
  extensionId: this.options.extensionWorldId,
858
895
  })
859
896
  );
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "setVersion": "1.18.13",
3
+ "setVersion": "1.18.15",
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.13",
3
+ "version": "1.18.15",
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-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",
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-browser-ui.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/chromium-launch.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\"",
@@ -79,8 +79,8 @@
79
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.41.4",
83
- "@ai-ecoverse/slicc-shared-web": "2.12.1",
82
+ "@ai-ecoverse/slicc-cdp": "1.41.17",
83
+ "@ai-ecoverse/slicc-shared-web": "2.12.3",
84
84
  "@biomejs/biome": "2.5.15",
85
85
  "ajv": "8.20.0",
86
86
  "ajv-formats": "3.0.1",