@riddledc/riddle-proof 0.7.170 → 0.7.172

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 CHANGED
@@ -398,7 +398,7 @@ when body matching overrides sequence order.
398
398
  appears only after a picker, tab, login stub, storage seed, form fill,
399
399
  transport control, or other bounded interaction. Supported setup actions are
400
400
  `click`, `drag`, `press`, `fill`, `set_input_value`, `set_range_value`,
401
- `canvas_signature`, `assert_text_visible`, `assert_text_absent`,
401
+ `deterministic_runtime`, `canvas_signature`, `assert_text_visible`, `assert_text_absent`,
402
402
  `assert_selector_count`, `assert_window_value`, `assert_window_number`,
403
403
  `local_storage`, `session_storage`, `clear_storage`, `clear_console`,
404
404
  `screenshot`, `wait`, `wait_for_selector`, `wait_for_text`, `window_eval`,
@@ -423,6 +423,14 @@ events, and records the requested value plus the browser's actual normalized
423
423
  value, numeric value, `min`, `max`, and `step`. The action is intentionally
424
424
  strict: if the target is not an `input[type="range"]`, setup fails with
425
425
  `not_range_input` instead of silently treating the control like a text field.
426
+ Use `deterministic_runtime` when randomized or clock-driven gameplay needs a
427
+ stable proof path. It can install a deterministic `Math.random` queue with
428
+ `random_queue` / `randomValues`, pin `Date.now()` with `now` / `mockNow`,
429
+ advance the pinned clock with `advance_ms`, append more random values with
430
+ `append: true`, and restore browser originals with `restore: true`. Receipts
431
+ record whether random and clock mocks are active, queue length, clock time, and
432
+ random-queue underflows. Values in `random_queue` must be finite numbers from
433
+ `0` inclusive to `1` exclusive.
426
434
  Use `canvas_signature` for canvas-only proof surfaces. It requires `selector`,
427
435
  reads the selected canvas with `toDataURL("image/png")`, records a sampled hash,
428
436
  canvas dimensions, CSS dimensions, and data length, and can store the result
@@ -49,6 +49,7 @@ var RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES = [
49
49
  "fill",
50
50
  "set_input_value",
51
51
  "set_range_value",
52
+ "deterministic_runtime",
52
53
  "canvas_signature",
53
54
  "assert_text_visible",
54
55
  "assert_text_absent",
@@ -357,11 +358,19 @@ function resolveJsonPath(root, path) {
357
358
  }
358
359
  let current = root;
359
360
  for (const segment of segments) {
360
- if (typeof segment === "number") {
361
- if (!Array.isArray(current) || segment < 0 || segment >= current.length) return { exists: false };
362
- current = current[segment];
361
+ if (Array.isArray(current)) {
362
+ if (segment === "length") {
363
+ current = current.length;
364
+ continue;
365
+ }
366
+ const index = typeof segment === "number" ? segment : /^\d+$/.test(segment) ? Number(segment) : -1;
367
+ if (index < 0 || index >= current.length) return { exists: false };
368
+ current = current[index];
363
369
  continue;
364
370
  }
371
+ if (typeof segment === "number") {
372
+ return { exists: false };
373
+ }
365
374
  if (!isRecord(current) || !hasOwn(current, segment)) return { exists: false };
366
375
  current = current[segment];
367
376
  }
@@ -503,6 +512,23 @@ function profileSetupWindowEvalReceipts(results) {
503
512
  return receipt;
504
513
  });
505
514
  }
515
+ function profileSetupDeterministicRuntimeReceipts(results) {
516
+ return results.filter((result) => profileSetupResultAction(result) === "deterministic_runtime").map((result) => ({
517
+ ordinal: result.ordinal ?? null,
518
+ ok: result.ok !== false,
519
+ random_enabled: result.random_enabled ?? null,
520
+ random_queue_added: result.random_queue_added ?? null,
521
+ random_queue_length: result.random_queue_length ?? null,
522
+ random_queue_mode: result.random_queue_mode ?? null,
523
+ random_underflow_count: result.random_underflow_count ?? null,
524
+ clock_enabled: result.clock_enabled ?? null,
525
+ previous_now: result.previous_now ?? null,
526
+ now: result.now ?? null,
527
+ advance_ms: result.advance_ms ?? null,
528
+ restored: result.restored ?? null,
529
+ reason: result.reason ?? result.error ?? null
530
+ }));
531
+ }
506
532
  function profileSetupReturnSummaryFields(result) {
507
533
  const input = result.return_summary_fields;
508
534
  if (!Array.isArray(input)) return [];
@@ -717,6 +743,8 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
717
743
  const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
718
744
  const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
719
745
  const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
746
+ const deterministicRuntimeReceipts = profileSetupDeterministicRuntimeReceipts(results);
747
+ const sampledDeterministicRuntimeReceipts = sampleProfileSetupSummaryItems(deterministicRuntimeReceipts, 8);
720
748
  const rangeValueReceipts = profileSetupRangeValueReceipts(results);
721
749
  const sampledRangeValueReceipts = sampleProfileSetupSummaryItems(rangeValueReceipts, 8);
722
750
  const dragReceipts = profileSetupDragReceipts(results);
@@ -776,6 +804,9 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountByViewpo
776
804
  window_eval_captured_total: windowEvalCapturedTotal,
777
805
  window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
778
806
  window_eval: sampledWindowEvalReceipts,
807
+ deterministic_runtime_total: deterministicRuntimeReceipts.length,
808
+ deterministic_runtime_truncated: deterministicRuntimeReceipts.length > sampledDeterministicRuntimeReceipts.length,
809
+ deterministic_runtime: sampledDeterministicRuntimeReceipts,
779
810
  set_range_value_total: rangeValueReceipts.length,
780
811
  set_range_value_truncated: rangeValueReceipts.length > sampledRangeValueReceipts.length,
781
812
  set_range_value: sampledRangeValueReceipts,
@@ -838,7 +869,7 @@ function isSupportedCheckType(value) {
838
869
  }
839
870
  function normalizeSetupActionType(value, index) {
840
871
  const normalizedInput = String(value || "").trim().replace(/-/g, "_");
841
- const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "reset_console" || normalizedInput === "clear_browser_console" || normalizedInput === "reset_browser_console" ? "clear_console" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "set_slider_value" || normalizedInput === "slider_value" || normalizedInput === "set_slider" || normalizedInput === "set_range" || normalizedInput === "range_value" || normalizedInput === "range_input" || normalizedInput === "set_range_input" ? "set_range_value" : normalizedInput === "canvas_hash" || normalizedInput === "capture_canvas_hash" || normalizedInput === "capture_canvas_signature" || normalizedInput === "canvas_state_signature" ? "canvas_signature" : normalizedInput === "capture_screenshot" || normalizedInput === "save_screenshot" || normalizedInput === "setup_screenshot" ? "screenshot" : normalizedInput === "accept_dialog" || normalizedInput === "accept_dialogs" || normalizedInput === "confirm_dialog" || normalizedInput === "set_dialog_response" ? "dialog_response" : normalizedInput === "dismiss_dialog" || normalizedInput === "dismiss_dialogs" || normalizedInput === "cancel_dialog" ? "dialog_response" : normalizedInput === "window_call_until" || normalizedInput === "call_until" || normalizedInput === "window_call_repeat_until" || normalizedInput === "repeat_window_call_until" ? "window_call_until" : normalizedInput === "window_evaluate" || normalizedInput === "browser_eval" || normalizedInput === "browser_evaluate" || normalizedInput === "evaluate_script" || normalizedInput === "profile_script" ? "window_eval" : normalizedInput;
872
+ const normalized = normalizedInput === "clear_browser_storage" ? "clear_storage" : normalizedInput === "reset_console" || normalizedInput === "clear_browser_console" || normalizedInput === "reset_browser_console" ? "clear_console" : normalizedInput === "pointer_drag" || normalizedInput === "mouse_drag" || normalizedInput === "drag_to" ? "drag" : normalizedInput === "keyboard_press" || normalizedInput === "key_press" ? "press" : normalizedInput === "set_slider_value" || normalizedInput === "slider_value" || normalizedInput === "set_slider" || normalizedInput === "set_range" || normalizedInput === "range_value" || normalizedInput === "range_input" || normalizedInput === "set_range_input" ? "set_range_value" : normalizedInput === "deterministic_runtime" || normalizedInput === "mock_runtime" || normalizedInput === "mock_random" || normalizedInput === "mock_random_queue" || normalizedInput === "seed_random_queue" || normalizedInput === "set_random_queue" || normalizedInput === "mock_clock" || normalizedInput === "set_mock_clock" || normalizedInput === "set_runtime_determinism" || normalizedInput === "runtime_determinism" ? "deterministic_runtime" : normalizedInput === "canvas_hash" || normalizedInput === "capture_canvas_hash" || normalizedInput === "capture_canvas_signature" || normalizedInput === "canvas_state_signature" ? "canvas_signature" : normalizedInput === "capture_screenshot" || normalizedInput === "save_screenshot" || normalizedInput === "setup_screenshot" ? "screenshot" : normalizedInput === "accept_dialog" || normalizedInput === "accept_dialogs" || normalizedInput === "confirm_dialog" || normalizedInput === "set_dialog_response" ? "dialog_response" : normalizedInput === "dismiss_dialog" || normalizedInput === "dismiss_dialogs" || normalizedInput === "cancel_dialog" ? "dialog_response" : normalizedInput === "window_call_until" || normalizedInput === "call_until" || normalizedInput === "window_call_repeat_until" || normalizedInput === "repeat_window_call_until" ? "window_call_until" : normalizedInput === "window_evaluate" || normalizedInput === "browser_eval" || normalizedInput === "browser_evaluate" || normalizedInput === "evaluate_script" || normalizedInput === "profile_script" ? "window_eval" : normalizedInput;
842
873
  if (RIDDLE_PROOF_PROFILE_SETUP_ACTION_TYPES.includes(normalized)) {
843
874
  return normalized;
844
875
  }
@@ -957,6 +988,39 @@ function normalizeSetupActionScreenshotFullPage(input, type, index) {
957
988
  }
958
989
  return values[0];
959
990
  }
991
+ function normalizeSetupActionRandomQueue(input, index) {
992
+ const rawQueue = valueFromOwn(
993
+ input,
994
+ "random_queue",
995
+ "randomQueue",
996
+ "random_values",
997
+ "randomValues",
998
+ "random_sequence",
999
+ "randomSequence",
1000
+ "math_random",
1001
+ "mathRandom"
1002
+ );
1003
+ if (rawQueue === void 0) return void 0;
1004
+ if (!Array.isArray(rawQueue) || rawQueue.length === 0) {
1005
+ throw new Error(`target.setup_actions[${index}].random_queue must be a non-empty array of numbers from 0 inclusive to 1 exclusive.`);
1006
+ }
1007
+ return rawQueue.map((item, queueIndex) => {
1008
+ const value = numberValue(item);
1009
+ if (value === void 0 || value < 0 || value >= 1) {
1010
+ throw new Error(`target.setup_actions[${index}].random_queue[${queueIndex}] must be a finite number from 0 inclusive to 1 exclusive.`);
1011
+ }
1012
+ return value;
1013
+ });
1014
+ }
1015
+ function normalizeSetupActionNonNegativeNumber(input, index, outputKey, ...keys) {
1016
+ const rawValue = valueFromOwn(input, ...keys);
1017
+ if (rawValue === void 0) return void 0;
1018
+ const value = numberValue(rawValue);
1019
+ if (value === void 0 || value < 0) {
1020
+ throw new Error(`target.setup_actions[${index}].${outputKey} must be a finite non-negative number.`);
1021
+ }
1022
+ return value;
1023
+ }
960
1024
  function normalizeSetupAction(input, index) {
961
1025
  if (!isRecord(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
962
1026
  const type = normalizeSetupActionType(stringValue(input.type), index);
@@ -1017,6 +1081,14 @@ function normalizeSetupAction(input, index) {
1017
1081
  if ((type === "fill" || type === "set_input_value" || type === "set_range_value") && value === void 0 && !hasJsonValue) {
1018
1082
  throw new Error(`target.setup_actions[${index}] ${type} requires value.`);
1019
1083
  }
1084
+ const randomQueue = type === "deterministic_runtime" ? normalizeSetupActionRandomQueue(input, index) : void 0;
1085
+ const deterministicNow = type === "deterministic_runtime" ? normalizeSetupActionNonNegativeNumber(input, index, "now", "now", "date_now", "dateNow", "mock_now", "mockNow", "clock", "timestamp", "time_ms", "timeMs") : void 0;
1086
+ const deterministicAdvanceMs = type === "deterministic_runtime" ? normalizeSetupActionNonNegativeNumber(input, index, "advance_ms", "advance_ms", "advanceMs", "tick_ms", "tickMs", "add_ms", "addMs") : void 0;
1087
+ const deterministicAppend = type === "deterministic_runtime" && booleanValue(valueFromOwn(input, "append", "append_random", "appendRandom")) === true;
1088
+ const deterministicRestore = type === "deterministic_runtime" && booleanValue(valueFromOwn(input, "restore", "reset", "restore_originals", "restoreOriginals")) === true;
1089
+ if (type === "deterministic_runtime" && randomQueue === void 0 && deterministicNow === void 0 && deterministicAdvanceMs === void 0 && !deterministicRestore) {
1090
+ throw new Error(`target.setup_actions[${index}] deterministic_runtime requires random_queue, now, advance_ms, or restore.`);
1091
+ }
1020
1092
  const key = stringValue(input.key);
1021
1093
  let dialogAccept;
1022
1094
  if (type === "dialog_response") {
@@ -1124,6 +1196,11 @@ function normalizeSetupAction(input, index) {
1124
1196
  key,
1125
1197
  value,
1126
1198
  value_json: hasJsonValue ? toJsonValue(input.value_json ?? input.valueJson ?? input.json) : void 0,
1199
+ random_queue: randomQueue,
1200
+ now: deterministicNow,
1201
+ advance_ms: deterministicAdvanceMs,
1202
+ append: deterministicAppend || void 0,
1203
+ restore: deterministicRestore || void 0,
1127
1204
  label: stringFromOwn(input, "label", "name", "screenshot_label", "screenshotLabel"),
1128
1205
  script,
1129
1206
  path,
@@ -4200,6 +4277,25 @@ function profileSetupWindowEvalReceipts(results) {
4200
4277
  return receipt;
4201
4278
  });
4202
4279
  }
4280
+ function profileSetupDeterministicRuntimeReceipts(results) {
4281
+ return (results || [])
4282
+ .filter((result) => result && profileSetupResultAction(result) === "deterministic_runtime")
4283
+ .map((result) => ({
4284
+ ordinal: result.ordinal ?? null,
4285
+ ok: result.ok !== false,
4286
+ random_enabled: result.random_enabled ?? null,
4287
+ random_queue_added: result.random_queue_added ?? null,
4288
+ random_queue_length: result.random_queue_length ?? null,
4289
+ random_queue_mode: result.random_queue_mode ?? null,
4290
+ random_underflow_count: result.random_underflow_count ?? null,
4291
+ clock_enabled: result.clock_enabled ?? null,
4292
+ previous_now: result.previous_now ?? null,
4293
+ now: result.now ?? null,
4294
+ advance_ms: result.advance_ms ?? null,
4295
+ restored: result.restored ?? null,
4296
+ reason: result.reason || result.error || null,
4297
+ }));
4298
+ }
4203
4299
  function profileSetupReturnSummaryFields(result) {
4204
4300
  const input = result && result.return_summary_fields;
4205
4301
  if (!Array.isArray(input)) return [];
@@ -4443,6 +4539,8 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
4443
4539
  const windowEvalStoredTotal = windowEvalReceipts.filter((result) => typeof result.return_stored_to === "string" && result.return_stored_to.trim()).length;
4444
4540
  const windowEvalCapturedTotal = windowEvalReceipts.filter((result) => result.return_captured === true).length;
4445
4541
  const sampledWindowEvalReceipts = sampleProfileSetupSummaryItems(windowEvalReceipts, 8);
4542
+ const deterministicRuntimeReceipts = profileSetupDeterministicRuntimeReceipts(results);
4543
+ const sampledDeterministicRuntimeReceipts = sampleProfileSetupSummaryItems(deterministicRuntimeReceipts, 8);
4446
4544
  const rangeValueReceipts = profileSetupRangeValueReceipts(results);
4447
4545
  const sampledRangeValueReceipts = sampleProfileSetupSummaryItems(rangeValueReceipts, 8);
4448
4546
  const dragReceipts = profileSetupDragReceipts(results);
@@ -4512,6 +4610,9 @@ function profileSetupSummary(viewports, actionCount, expectedActionCountsByViewp
4512
4610
  window_eval_captured_total: windowEvalCapturedTotal,
4513
4611
  window_eval_truncated: windowEvalReceipts.length > sampledWindowEvalReceipts.length,
4514
4612
  window_eval: sampledWindowEvalReceipts,
4613
+ deterministic_runtime_total: deterministicRuntimeReceipts.length,
4614
+ deterministic_runtime_truncated: deterministicRuntimeReceipts.length > sampledDeterministicRuntimeReceipts.length,
4615
+ deterministic_runtime: sampledDeterministicRuntimeReceipts,
4515
4616
  set_range_value_total: rangeValueReceipts.length,
4516
4617
  set_range_value_truncated: rangeValueReceipts.length > sampledRangeValueReceipts.length,
4517
4618
  set_range_value: sampledRangeValueReceipts,
@@ -6133,6 +6234,111 @@ async function executeSetupAction(action, ordinal, viewport) {
6133
6234
  }
6134
6235
  return { ...base, ...setupScopeEvidence(scope), ok: true, storage, reload: action.reload === true };
6135
6236
  }
6237
+ if (type === "deterministic_runtime") {
6238
+ const scope = await setupActionScope(action, timeout);
6239
+ if (!scope.ok) return setupScopeFailure(base, scope);
6240
+ const randomQueue = Array.isArray(action.random_queue)
6241
+ ? action.random_queue
6242
+ : Array.isArray(action.randomQueue)
6243
+ ? action.randomQueue
6244
+ : null;
6245
+ const now = setupFiniteNumber(action.now ?? action.date_now ?? action.dateNow ?? action.mock_now ?? action.mockNow ?? action.clock ?? action.timestamp ?? action.time_ms ?? action.timeMs);
6246
+ const advanceMs = setupFiniteNumber(action.advance_ms ?? action.advanceMs ?? action.tick_ms ?? action.tickMs ?? action.add_ms ?? action.addMs);
6247
+ const append = action.append === true || action.append_random === true || action.appendRandom === true;
6248
+ const restore = action.restore === true || action.reset === true || action.restore_originals === true || action.restoreOriginals === true;
6249
+ const runtimeResult = await scope.context.evaluate((payload) => {
6250
+ const root = window;
6251
+ const stateKey = "__RIDDLE_PROOF_DETERMINISTIC_RUNTIME__";
6252
+ const state = root[stateKey] && typeof root[stateKey] === "object" && !Array.isArray(root[stateKey])
6253
+ ? root[stateKey]
6254
+ : {};
6255
+ root[stateKey] = state;
6256
+ if (typeof state.originalRandom !== "function") state.originalRandom = Math.random;
6257
+ if (typeof state.originalDateNow !== "function") state.originalDateNow = Date.now;
6258
+ const previousNow = typeof state.now === "number" && Number.isFinite(state.now)
6259
+ ? state.now
6260
+ : Date.now === state.originalDateNow
6261
+ ? null
6262
+ : Date.now();
6263
+ if (payload.restore) {
6264
+ Math.random = state.originalRandom;
6265
+ Date.now = state.originalDateNow;
6266
+ delete root[stateKey];
6267
+ return {
6268
+ ok: true,
6269
+ restored: true,
6270
+ random_enabled: false,
6271
+ random_queue_added: 0,
6272
+ random_queue_length: 0,
6273
+ random_queue_mode: null,
6274
+ random_underflow_count: typeof state.randomUnderflowCount === "number" ? state.randomUnderflowCount : 0,
6275
+ clock_enabled: false,
6276
+ previous_now: previousNow,
6277
+ now: null,
6278
+ advance_ms: null,
6279
+ };
6280
+ }
6281
+ let randomQueueAdded = null;
6282
+ let randomQueueMode = null;
6283
+ if (Array.isArray(payload.random_queue)) {
6284
+ const queue = payload.random_queue.filter((value) => typeof value === "number" && Number.isFinite(value) && value >= 0 && value < 1);
6285
+ const existing = Array.isArray(state.randomQueue) ? state.randomQueue : [];
6286
+ state.randomQueue = payload.append ? existing.concat(queue) : queue.slice();
6287
+ randomQueueAdded = queue.length;
6288
+ randomQueueMode = payload.append ? "append" : "replace";
6289
+ Math.random = function riddleProofMockRandom() {
6290
+ const activeQueue = Array.isArray(state.randomQueue) ? state.randomQueue : [];
6291
+ if (activeQueue.length) return activeQueue.shift();
6292
+ state.randomUnderflowCount = (typeof state.randomUnderflowCount === "number" ? state.randomUnderflowCount : 0) + 1;
6293
+ return 0;
6294
+ };
6295
+ }
6296
+ if (typeof payload.now === "number" && Number.isFinite(payload.now)) {
6297
+ state.now = payload.now;
6298
+ Date.now = function riddleProofMockDateNow() {
6299
+ return state.now;
6300
+ };
6301
+ }
6302
+ if (typeof payload.advance_ms === "number" && Number.isFinite(payload.advance_ms)) {
6303
+ const baseNow = typeof state.now === "number" && Number.isFinite(state.now)
6304
+ ? state.now
6305
+ : Date.now();
6306
+ state.now = baseNow + payload.advance_ms;
6307
+ Date.now = function riddleProofMockDateNow() {
6308
+ return state.now;
6309
+ };
6310
+ }
6311
+ return {
6312
+ ok: true,
6313
+ restored: false,
6314
+ random_enabled: Math.random !== state.originalRandom,
6315
+ random_queue_added: randomQueueAdded,
6316
+ random_queue_length: Array.isArray(state.randomQueue) ? state.randomQueue.length : 0,
6317
+ random_queue_mode: randomQueueMode,
6318
+ random_underflow_count: typeof state.randomUnderflowCount === "number" ? state.randomUnderflowCount : 0,
6319
+ clock_enabled: Date.now !== state.originalDateNow,
6320
+ previous_now: previousNow,
6321
+ now: typeof state.now === "number" && Number.isFinite(state.now) ? state.now : null,
6322
+ advance_ms: typeof payload.advance_ms === "number" && Number.isFinite(payload.advance_ms) ? payload.advance_ms : null,
6323
+ };
6324
+ }, { random_queue: randomQueue, now, advance_ms: advanceMs, append, restore });
6325
+ return {
6326
+ ...base,
6327
+ ...setupScopeEvidence(scope),
6328
+ ok: runtimeResult && runtimeResult.ok === true,
6329
+ random_enabled: runtimeResult?.random_enabled,
6330
+ random_queue_added: runtimeResult?.random_queue_added,
6331
+ random_queue_length: runtimeResult?.random_queue_length,
6332
+ random_queue_mode: runtimeResult?.random_queue_mode,
6333
+ random_underflow_count: runtimeResult?.random_underflow_count,
6334
+ clock_enabled: runtimeResult?.clock_enabled,
6335
+ previous_now: runtimeResult?.previous_now,
6336
+ now: runtimeResult?.now,
6337
+ advance_ms: runtimeResult?.advance_ms,
6338
+ restored: runtimeResult?.restored,
6339
+ reason: runtimeResult && runtimeResult.ok === true ? undefined : runtimeResult?.reason || "deterministic_runtime_not_applied",
6340
+ };
6341
+ }
6136
6342
  if (type === "window_eval") {
6137
6343
  const script = String(action.script || action.code || action.source || action.body || "");
6138
6344
  const args = Array.isArray(action.args) ? action.args : [];
@@ -7179,11 +7385,17 @@ function resolveJsonProbePath(root, path) {
7179
7385
  }
7180
7386
  let current = root;
7181
7387
  for (const segment of segments) {
7182
- if (typeof segment === "number") {
7183
- if (!Array.isArray(current) || segment < 0 || segment >= current.length) return { exists: false };
7184
- current = current[segment];
7388
+ if (Array.isArray(current)) {
7389
+ if (segment === "length") {
7390
+ current = current.length;
7391
+ continue;
7392
+ }
7393
+ const index = typeof segment === "number" ? segment : (/^\d+$/.test(segment) ? Number(segment) : -1);
7394
+ if (index < 0 || index >= current.length) return { exists: false };
7395
+ current = current[index];
7185
7396
  continue;
7186
7397
  }
7398
+ if (typeof segment === "number") return { exists: false };
7187
7399
  if (!current || typeof current !== "object" || Array.isArray(current) || !Object.hasOwn(current, segment)) {
7188
7400
  return { exists: false };
7189
7401
  }