@ai-ecoverse/slicc-browsers 1.20.0 → 1.20.1

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.
@@ -160,32 +160,103 @@ async function key(client, reader, session, observer, beforeSend, requireTyped =
160
160
  return { out, ok: out.ok && (!requireTyped || typed === true) };
161
161
  }
162
162
 
163
- async function inputMethods(client, session, methods) {
163
+ function clearPoint(box) {
164
+ const point = { x: 20, y: 20 };
165
+ if (!box || !(box.w > 0) || !(box.h > 0)) return point;
166
+ const left = box.x - box.w / 2;
167
+ const right = box.x + box.w / 2;
168
+ const top = box.y - box.h / 2;
169
+ const bottom = box.y + box.h / 2;
170
+ if (point.x < left || point.x > right || point.y < top || point.y > bottom) return point;
171
+ return { x: 20, y: Math.max(20, bottom + 40) };
172
+ }
173
+
174
+ function shownish(text) {
175
+ return Boolean(text && (text === SHOWN || /^slicc: refused/.test(text)));
176
+ }
177
+
178
+ function inputOutcome(outs, missing, name, side) {
179
+ const [first, ...rest] = outs;
180
+ const firstRefusal = refusal(first);
181
+ if (shownish(firstRefusal)) return { ok: false, refusal: firstRefusal };
182
+ if (!first.ok) {
183
+ missing.push(`${name}: ${firstRefusal || 'transport error'}`);
184
+ return { ok: 'incomplete', refusal: null };
185
+ }
186
+ if (side === 'control') {
187
+ for (const out of rest) {
188
+ if (out.ok) continue;
189
+ missing.push(`${name}: cleanup ${refusal(out) || 'transport error'}`);
190
+ }
191
+ }
192
+ return { ok: true, refusal: null };
193
+ }
194
+
195
+ async function sendPair(client, session, method, down, up) {
196
+ const first = await outcome(client.send(method, down, session));
197
+ if (shownish(refusal(first))) return [first];
198
+ return [first, await outcome(client.send(method, up, session))];
199
+ }
200
+
201
+ async function inputMethods(client, session, methods, point, missing, side) {
164
202
  const results = {};
203
+ const { x, y } = point;
204
+ const drag = { items: [], files: [], dragOperationsMask: 1 };
165
205
  for (const method of methods) {
166
- let params = {};
167
- if (method === 'Input.dispatchKeyEvent') params = { type: 'keyDown', key: 'Tab', code: 'Tab' };
206
+ const name = method.slice('Input.'.length);
207
+ let outs;
208
+ if (method === 'Input.dispatchKeyEvent')
209
+ outs = [
210
+ await outcome(client.send(method, { type: 'keyDown', key: 'Tab', code: 'Tab' }, session)),
211
+ ];
168
212
  else if (method === 'Input.dispatchMouseEvent')
169
- params = { type: 'mousePressed', x: 20, y: 20, button: 'left', clickCount: 1 };
213
+ outs = await sendPair(
214
+ client,
215
+ session,
216
+ method,
217
+ { type: 'mousePressed', x, y, button: 'left', clickCount: 1 },
218
+ { type: 'mouseReleased', x, y, button: 'left', clickCount: 1 }
219
+ );
170
220
  else if (method === 'Input.dispatchTouchEvent')
171
- params = { type: 'touchStart', touchPoints: [{ x: 20, y: 20 }] };
221
+ outs = await sendPair(
222
+ client,
223
+ session,
224
+ method,
225
+ { type: 'touchStart', touchPoints: [{ x, y }] },
226
+ { type: 'touchEnd', touchPoints: [] }
227
+ );
172
228
  else if (method === 'Input.dispatchDragEvent')
173
- params = {
174
- type: 'dragEnter',
175
- x: 20,
176
- y: 20,
177
- data: { items: [], files: [], dragOperationsMask: 1 },
178
- };
229
+ outs = await sendPair(
230
+ client,
231
+ session,
232
+ method,
233
+ { type: 'dragEnter', x, y, data: drag },
234
+ { type: 'dragCancel', x, y, data: drag }
235
+ );
179
236
  else if (method === 'Input.emulateTouchFromMouseEvent')
180
- params = { type: 'mousePressed', x: 20, y: 20, button: 'left', clickCount: 1 };
181
- else if (method === 'Input.insertText') params = { text: 'k' };
237
+ outs = await sendPair(
238
+ client,
239
+ session,
240
+ method,
241
+ { type: 'mousePressed', x, y, button: 'left', clickCount: 1 },
242
+ { type: 'mouseReleased', x, y, button: 'left', clickCount: 1 }
243
+ );
244
+ else if (method === 'Input.insertText')
245
+ outs = [await outcome(client.send(method, { text: 'k' }, session))];
182
246
  else if (method === 'Input.imeSetComposition')
183
- params = { text: 'k', selectionStart: 1, selectionEnd: 1 };
184
- else if (method === 'Input.synthesizePinchGesture') params = { x: 20, y: 20, scaleFactor: 1.1 };
185
- else if (method === 'Input.synthesizeScrollGesture') params = { x: 20, y: 20, yDistance: -10 };
186
- else if (method === 'Input.synthesizeTapGesture') params = { x: 20, y: 20 };
187
- const out = await outcome(client.send(method, params, session));
188
- results[method.slice('Input.'.length)] = { ok: out.ok, refusal: refusal(out) };
247
+ outs = [
248
+ await outcome(
249
+ client.send(method, { text: 'k', selectionStart: 1, selectionEnd: 1 }, session)
250
+ ),
251
+ ];
252
+ else if (method === 'Input.synthesizePinchGesture')
253
+ outs = [await outcome(client.send(method, { x, y, scaleFactor: 1.1 }, session))];
254
+ else if (method === 'Input.synthesizeScrollGesture')
255
+ outs = [await outcome(client.send(method, { x, y, yDistance: -10 }, session))];
256
+ else if (method === 'Input.synthesizeTapGesture')
257
+ outs = [await outcome(client.send(method, { x, y }, session))];
258
+ else outs = [await outcome(client.send(method, {}, session))];
259
+ results[name] = inputOutcome(outs, missing, name, side);
189
260
  }
190
261
  return results;
191
262
  }
@@ -697,7 +768,7 @@ async function holdFocus(reader, frame) {
697
768
  }
698
769
  }
699
770
 
700
- async function driveInput(client, reader, page, observer, inputList, mode, frame) {
771
+ async function driveInput(client, reader, page, observer, inputList, mode, frame, missing, side) {
701
772
  const visible = await observe(
702
773
  reader,
703
774
  observer,
@@ -734,6 +805,7 @@ async function driveInput(client, reader, page, observer, inputList, mode, frame
734
805
  return { x: r.left + r.width / 2, y: r.top + r.height / 2, w: r.width, h: r.height };
735
806
  })()`
736
807
  );
808
+ const point = clearPoint(box);
737
809
  const refocus = async () => {
738
810
  if (!(mode === 'focused' && frame)) return;
739
811
  await holdFocus(reader, frame);
@@ -761,7 +833,7 @@ async function driveInput(client, reader, page, observer, inputList, mode, frame
761
833
  await refocus();
762
834
  const typed = await key(client, reader, page, observer, refocus, mode !== 'focused');
763
835
  await refocus();
764
- const inputs = await inputMethods(client, page, inputList);
836
+ const inputs = await inputMethods(client, page, inputList, point, missing, side);
765
837
  await refocus();
766
838
  const focusedKey = await outcome(
767
839
  client.send('Input.dispatchKeyEvent', { type: 'keyDown', key: 'a', code: 'KeyA' }, page)
@@ -873,6 +945,51 @@ export async function driveReveal(client, reader, page, observer, frameMs, missi
873
945
  };
874
946
  }
875
947
 
948
+ function frameObservations({ pageAttached, origin, read, leaks, picture, input, captures }) {
949
+ return {
950
+ exists: true,
951
+ attached: pageAttached,
952
+ read: read.ok && read.result.result?.value === origin && !carries(read.result),
953
+ snapshot: leaks.snapshot,
954
+ snapshotFrameRead: leaks.snapshotFrameRead,
955
+ frameTreeLeak: leaks.frameTreeLeak,
956
+ documentLeak: leaks.documentLeak,
957
+ shadowDocumentLeak: leaks.shadowDocumentLeak,
958
+ axLeak: leaks.axLeak,
959
+ evaluateLeak: leaks.evaluateLeak,
960
+ partialAxLeak: leaks.partialAxLeak,
961
+ describeNodeLeak: leaks.describeNodeLeak,
962
+ outerHTMLLeak: leaks.outerHTMLLeak,
963
+ shot: picture.ok,
964
+ shotRefusal: refusal(picture.out),
965
+ click: input.pressed.ok,
966
+ clickRefusal: refusal(input.pressed.out),
967
+ key: input.typed.ok,
968
+ keyRefusal: refusal(input.typed.out),
969
+ frameClick: input.frameClick.ok,
970
+ frameClickRefusal: refusal(input.frameClick.out),
971
+ tab: input.tab.ok,
972
+ tabRefusal: refusal(input.tab),
973
+ frameVisible: input.visible === true,
974
+ frameFocused: input.frameFocused === true,
975
+ focusedKey: input.focusedKey.ok,
976
+ focusedKeyRefusal: refusal(input.focusedKey),
977
+ focusedText: input.focusedText.ok,
978
+ focusedTextRefusal: refusal(input.focusedText),
979
+ focusedIME: input.focusedIME.ok,
980
+ focusedIMERefusal: refusal(input.focusedIME),
981
+ archive: captures.archive.ok,
982
+ archiveRefusal: presentish(captures.archive),
983
+ pdf: captures.pdf.ok,
984
+ pdfRefusal: presentish(captures.pdf),
985
+ cast: captures.cast.ok,
986
+ castRefusal: presentish(captures.cast),
987
+ beginFrame: captures.begin.ok,
988
+ beginFrameRefusal: presentish(captures.begin),
989
+ inputs: input.inputs,
990
+ };
991
+ }
992
+
876
993
  export async function extensionFrame({
877
994
  client,
878
995
  reader,
@@ -950,50 +1067,27 @@ export async function extensionFrame({
950
1067
  });
951
1068
  if (mode === 'focused') await holdFocus(reader, frame);
952
1069
  const picture = await shot(client, page);
953
- const input = await driveInput(client, reader, page, observer, inputList, mode, frame);
1070
+ const input = await driveInput(
1071
+ client,
1072
+ reader,
1073
+ page,
1074
+ observer,
1075
+ inputList,
1076
+ mode,
1077
+ frame,
1078
+ missing,
1079
+ side
1080
+ );
954
1081
  const captures = await driveCaptures(client, page, missing);
955
- const result = {
956
- exists: true,
957
- attached: pageAttached,
958
- read: read.ok && read.result.result?.value === origin && !carries(read.result),
959
- snapshot: leaks.snapshot,
960
- snapshotFrameRead: leaks.snapshotFrameRead,
961
- frameTreeLeak: leaks.frameTreeLeak,
962
- documentLeak: leaks.documentLeak,
963
- shadowDocumentLeak: leaks.shadowDocumentLeak,
964
- axLeak: leaks.axLeak,
965
- evaluateLeak: leaks.evaluateLeak,
966
- partialAxLeak: leaks.partialAxLeak,
967
- describeNodeLeak: leaks.describeNodeLeak,
968
- outerHTMLLeak: leaks.outerHTMLLeak,
969
- shot: picture.ok,
970
- shotRefusal: refusal(picture.out),
971
- click: input.pressed.ok,
972
- clickRefusal: refusal(input.pressed.out),
973
- key: input.typed.ok,
974
- keyRefusal: refusal(input.typed.out),
975
- frameClick: input.frameClick.ok,
976
- frameClickRefusal: refusal(input.frameClick.out),
977
- tab: input.tab.ok,
978
- tabRefusal: refusal(input.tab),
979
- frameVisible: input.visible === true,
980
- frameFocused: input.frameFocused === true,
981
- focusedKey: input.focusedKey.ok,
982
- focusedKeyRefusal: refusal(input.focusedKey),
983
- focusedText: input.focusedText.ok,
984
- focusedTextRefusal: refusal(input.focusedText),
985
- focusedIME: input.focusedIME.ok,
986
- focusedIMERefusal: refusal(input.focusedIME),
987
- archive: captures.archive.ok,
988
- archiveRefusal: presentish(captures.archive),
989
- pdf: captures.pdf.ok,
990
- pdfRefusal: presentish(captures.pdf),
991
- cast: captures.cast.ok,
992
- castRefusal: presentish(captures.cast),
993
- beginFrame: captures.begin.ok,
994
- beginFrameRefusal: presentish(captures.begin),
995
- inputs: input.inputs,
996
- };
1082
+ const result = frameObservations({
1083
+ pageAttached,
1084
+ origin,
1085
+ read,
1086
+ leaks,
1087
+ picture,
1088
+ input,
1089
+ captures,
1090
+ });
997
1091
  if (castDrive) {
998
1092
  result.castBefore = castDrive.castBefore;
999
1093
  result.castBeforeRefusal = castDrive.castBeforeRefusal;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "setVersion": "1.20.0",
3
+ "setVersion": "1.20.1",
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.20.0",
3
+ "version": "1.20.1",
4
4
  "description": "SLICC's shared browser catalog, JSON schemas and discovery conformance corpus",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -73,7 +73,7 @@
73
73
  "validate": "node scripts/validate.mjs",
74
74
  "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",
75
75
  "format": "biome check --write . && gofmt -w . && cargo fmt",
76
- "test": "export PATH=\"$HOME/.cargo/bin:$PATH\" && node --test --test-concurrency=1 test/integration/debugger-stage1-packaging.test.mjs test/integration/debugger-raw-control.test.mjs test/integration/debugger-cleanup.test.mjs test/integration/debugger-stage1-install-vectors.test.mjs test/integration/protected-premise.test.mjs test/integration/debugger-stage1-vectors.test.mjs test/integration/self-contained.test.mjs test/integration/seven-corpus.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-unparseable-wipe.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-trusted-emulation.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-error-page-events.test.mjs test/integration/guard-error-page-reload.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-reveal-overlap.test.mjs test/integration/guard-extension-frames.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",
76
+ "test": "export PATH=\"$HOME/.cargo/bin:$PATH\" && node --test --test-concurrency=1 test/integration/debugger-stage1-packaging.test.mjs test/integration/debugger-raw-control.test.mjs test/integration/debugger-cleanup.test.mjs test/integration/debugger-stage1-install-vectors.test.mjs test/integration/protected-premise.test.mjs test/integration/debugger-stage1-vectors.test.mjs test/integration/self-contained.test.mjs test/integration/seven-corpus.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-unparseable-wipe.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-trusted-emulation.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-error-page-events.test.mjs test/integration/guard-error-page-reload.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-reveal-overlap.test.mjs test/integration/guard-extension-frame-mouse.test.mjs test/integration/guard-extension-frames.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",
77
77
  "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 ./...",
78
78
  "build": "go build ./... && cargo build --all-features && cargo build --target wasm32-wasip1 --all-features && npm pack --dry-run",
79
79
  "prepublishOnly": "node scripts/set-crate-version.mjs \"$npm_package_version\"",
@@ -86,7 +86,7 @@
86
86
  "devDependencies": {
87
87
  "@ai-ecoverse/slicc-cdp": "1.45.2",
88
88
  "@ai-ecoverse/slicc-shared-web": "2.13.10",
89
- "@biomejs/biome": "2.6.3",
89
+ "@biomejs/biome": "2.6.4",
90
90
  "ajv": "8.20.0",
91
91
  "ajv-formats": "3.0.1",
92
92
  "lefthook": "2.2.2",