haltija 1.3.3 → 1.3.4
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/apps/desktop/package.json +1 -1
- package/apps/desktop/resources/component.js +81 -66
- package/dist/component.d.ts +12 -1
- package/dist/component.esm.js +81 -66
- package/dist/component.js +81 -66
- package/dist/index.js +109 -70
- package/dist/server.js +109 -70
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -674,7 +674,7 @@ var injectorCode = `
|
|
|
674
674
|
`;
|
|
675
675
|
|
|
676
676
|
// src/version.ts
|
|
677
|
-
var VERSION = "1.3.
|
|
677
|
+
var VERSION = "1.3.4";
|
|
678
678
|
|
|
679
679
|
// src/embedded-assets.ts
|
|
680
680
|
var APP_MD = `# Haltija App
|
|
@@ -2485,7 +2485,14 @@ Great for debugging - check for errors after actions fail.
|
|
|
2485
2485
|
Run arbitrary JavaScript in the browser context. Returns the result.
|
|
2486
2486
|
|
|
2487
2487
|
The code runs in the page's context with access to window, document, etc.
|
|
2488
|
-
Return values are JSON-serialized.
|
|
2488
|
+
Return values are JSON-serialized.
|
|
2489
|
+
|
|
2490
|
+
Async code is supported: a returned Promise is awaited, and top-level \`await\`
|
|
2491
|
+
works. Multi-statement code needs an explicit \`return\` to produce a value.
|
|
2492
|
+
|
|
2493
|
+
document.title -> the title
|
|
2494
|
+
await fetch('/api').then(r => r.json()) -> the parsed body
|
|
2495
|
+
const r = await fetch('/api'); return r.status -> the status code
|
|
2489
2496
|
|
|
2490
2497
|
**Parameters:**
|
|
2491
2498
|
|
|
@@ -3021,7 +3028,7 @@ var COMPONENT_JS = `(() => {
|
|
|
3021
3028
|
});
|
|
3022
3029
|
|
|
3023
3030
|
// src/version.ts
|
|
3024
|
-
var VERSION = "1.3.
|
|
3031
|
+
var VERSION = "1.3.4";
|
|
3025
3032
|
|
|
3026
3033
|
// src/text-selector.ts
|
|
3027
3034
|
var TEXT_PSEUDO_RE = /:(?:text-is|has-text|text)\\(/;
|
|
@@ -3573,13 +3580,13 @@ var COMPONENT_JS = `(() => {
|
|
|
3573
3580
|
}
|
|
3574
3581
|
function resolveRefOrSelector(ref, selector) {
|
|
3575
3582
|
if (ref) {
|
|
3576
|
-
const
|
|
3577
|
-
if (
|
|
3583
|
+
const result = refRegistry.resolveWithStatus(ref);
|
|
3584
|
+
if (result.element) {
|
|
3578
3585
|
stats.refsResolved++;
|
|
3579
|
-
return { element:
|
|
3586
|
+
return { element: result.element, targetDesc: \`@\${ref}\` };
|
|
3580
3587
|
}
|
|
3581
3588
|
stats.refsStale++;
|
|
3582
|
-
const errorMsg =
|
|
3589
|
+
const errorMsg = result.status === "never_assigned" ? \`Ref @\${ref} was never assigned (highest ref is @\${refRegistry.getStats().highWaterMark})\` : result.status === "removed_from_dom" ? \`Ref @\${ref} points to an element that was removed from the DOM (try refreshing /tree)\` : \`Ref @\${ref} is stale - element was garbage collected (try refreshing /tree)\`;
|
|
3583
3590
|
return { element: null, targetDesc: \`@\${ref}\`, error: errorMsg };
|
|
3584
3591
|
}
|
|
3585
3592
|
if (selector) {
|
|
@@ -3590,13 +3597,13 @@ var COMPONENT_JS = `(() => {
|
|
|
3590
3597
|
}
|
|
3591
3598
|
function resolveRefOrSelectorAll(ref, selector) {
|
|
3592
3599
|
if (ref) {
|
|
3593
|
-
const
|
|
3594
|
-
if (
|
|
3600
|
+
const result = refRegistry.resolveWithStatus(ref);
|
|
3601
|
+
if (result.element) {
|
|
3595
3602
|
stats.refsResolved++;
|
|
3596
|
-
return { elements: [
|
|
3603
|
+
return { elements: [result.element], targetDesc: \`@\${ref}\` };
|
|
3597
3604
|
}
|
|
3598
3605
|
stats.refsStale++;
|
|
3599
|
-
const errorMsg =
|
|
3606
|
+
const errorMsg = result.status === "never_assigned" ? \`Ref @\${ref} was never assigned (highest ref is @\${refRegistry.getStats().highWaterMark})\` : result.status === "removed_from_dom" ? \`Ref @\${ref} points to an element that was removed from the DOM (try refreshing /tree)\` : \`Ref @\${ref} is stale - element was garbage collected (try refreshing /tree)\`;
|
|
3600
3607
|
return { elements: [], targetDesc: \`@\${ref}\`, error: errorMsg };
|
|
3601
3608
|
}
|
|
3602
3609
|
if (selector) {
|
|
@@ -5845,8 +5852,8 @@ var COMPONENT_JS = `(() => {
|
|
|
5845
5852
|
headers: { "Content-Type": "application/json" },
|
|
5846
5853
|
body: JSON.stringify({ action: "start", window: this.windowId })
|
|
5847
5854
|
});
|
|
5848
|
-
const
|
|
5849
|
-
if (
|
|
5855
|
+
const result = await response.json();
|
|
5856
|
+
if (result.success) {
|
|
5850
5857
|
this.isRecording = true;
|
|
5851
5858
|
this.serverManagedRecording = true;
|
|
5852
5859
|
this.recordingStartTime = Date.now();
|
|
@@ -5858,7 +5865,7 @@ var COMPONENT_JS = `(() => {
|
|
|
5858
5865
|
this.updateRecordingUI(true);
|
|
5859
5866
|
console.log("[Haltija] Recording started (server-managed)");
|
|
5860
5867
|
} else {
|
|
5861
|
-
console.error("[Haltija] Failed to start recording:",
|
|
5868
|
+
console.error("[Haltija] Failed to start recording:", result.error);
|
|
5862
5869
|
}
|
|
5863
5870
|
} catch (err) {
|
|
5864
5871
|
console.error("[Haltija] Failed to start recording:", err);
|
|
@@ -5873,10 +5880,10 @@ var COMPONENT_JS = `(() => {
|
|
|
5873
5880
|
headers: { "Content-Type": "application/json" },
|
|
5874
5881
|
body: JSON.stringify({ action: "stop", window: this.windowId })
|
|
5875
5882
|
});
|
|
5876
|
-
const
|
|
5877
|
-
if (
|
|
5878
|
-
this.recordingEvents =
|
|
5879
|
-
this.recordingStartTime =
|
|
5883
|
+
const result = await response.json();
|
|
5884
|
+
if (result.success && result.data) {
|
|
5885
|
+
this.recordingEvents = result.data.events || [];
|
|
5886
|
+
this.recordingStartTime = result.data.startTime || this.recordingStartTime;
|
|
5880
5887
|
const recordingId = \`rec_\${this.recordingStartTime}_\${Math.random().toString(36).slice(2, 8)}\`;
|
|
5881
5888
|
this.lastRecordingId = recordingId;
|
|
5882
5889
|
console.log(\`[Haltija] Recording stopped (\${this.recordingEvents.length} events)\`);
|
|
@@ -6189,15 +6196,15 @@ var COMPONENT_JS = `(() => {
|
|
|
6189
6196
|
headers: { "Content-Type": "application/json" },
|
|
6190
6197
|
body: JSON.stringify({ description, agentId })
|
|
6191
6198
|
});
|
|
6192
|
-
const
|
|
6193
|
-
if (
|
|
6199
|
+
const result = await response.json();
|
|
6200
|
+
if (result.error) {
|
|
6194
6201
|
if (successMsg) {
|
|
6195
|
-
successMsg.textContent = \`\u26A0\uFE0F \${
|
|
6202
|
+
successMsg.textContent = \`\u26A0\uFE0F \${result.error}\`;
|
|
6196
6203
|
successMsg.style.color = "#f59e0b";
|
|
6197
6204
|
}
|
|
6198
6205
|
} else {
|
|
6199
6206
|
if (successMsg) {
|
|
6200
|
-
successMsg.textContent = \`\u2713 Sent to \${agentName}\${
|
|
6207
|
+
successMsg.textContent = \`\u2713 Sent to \${agentName}\${result.interrupted ? " (interrupted)" : ""}\`;
|
|
6201
6208
|
successMsg.style.color = "#22c55e";
|
|
6202
6209
|
}
|
|
6203
6210
|
setTimeout(() => this.closeTestModal(), 1500);
|
|
@@ -6728,13 +6735,13 @@ var COMPONENT_JS = `(() => {
|
|
|
6728
6735
|
const haltija = window.haltija;
|
|
6729
6736
|
if (haltija?.openAgentTab) {
|
|
6730
6737
|
newAgentText.textContent = "Creating...";
|
|
6731
|
-
const
|
|
6732
|
-
if (
|
|
6738
|
+
const result = await haltija.openAgentTab();
|
|
6739
|
+
if (result?.shellId) {
|
|
6733
6740
|
await new Promise((r) => setTimeout(r, 300));
|
|
6734
6741
|
if (type === "selection") {
|
|
6735
|
-
this.sendSelectionToAgent(
|
|
6742
|
+
this.sendSelectionToAgent(result.shellId, result.name || "agent");
|
|
6736
6743
|
} else if (type === "recording") {
|
|
6737
|
-
this.sendRecordingToAgent(
|
|
6744
|
+
this.sendRecordingToAgent(result.shellId, result.name || "agent");
|
|
6738
6745
|
}
|
|
6739
6746
|
} else {
|
|
6740
6747
|
console.error(\`\${LOG_PREFIX} Failed to create agent tab\`);
|
|
@@ -6803,8 +6810,8 @@ var COMPONENT_JS = `(() => {
|
|
|
6803
6810
|
context: \`selection from \${window.location.host}\`
|
|
6804
6811
|
})
|
|
6805
6812
|
});
|
|
6806
|
-
const
|
|
6807
|
-
if (
|
|
6813
|
+
const result = await response.json();
|
|
6814
|
+
if (result.sent) {
|
|
6808
6815
|
this.clearSelection();
|
|
6809
6816
|
console.log(\`\${LOG_PREFIX} Selection sent to \${agentName}\`);
|
|
6810
6817
|
}
|
|
@@ -8319,11 +8326,11 @@ var COMPONENT_JS = `(() => {
|
|
|
8319
8326
|
this.respond(msg2.id, false, undefined, "Video capture requires the Haltija Desktop app. Run: npx haltija@latest -f");
|
|
8320
8327
|
return;
|
|
8321
8328
|
}
|
|
8322
|
-
haltija.startVideoCapture({ maxDuration: payload2.maxDuration }).then((
|
|
8323
|
-
if (
|
|
8324
|
-
this.respond(msg2.id, true, { recordingId:
|
|
8329
|
+
haltija.startVideoCapture({ maxDuration: payload2.maxDuration }).then((result) => {
|
|
8330
|
+
if (result.success) {
|
|
8331
|
+
this.respond(msg2.id, true, { recordingId: result.recordingId });
|
|
8325
8332
|
} else {
|
|
8326
|
-
this.respond(msg2.id, false, undefined,
|
|
8333
|
+
this.respond(msg2.id, false, undefined, result.error || "Failed to start video");
|
|
8327
8334
|
}
|
|
8328
8335
|
}).catch((err) => {
|
|
8329
8336
|
this.respond(msg2.id, false, undefined, \`Failed to start video: \${err.message}\`);
|
|
@@ -8333,11 +8340,11 @@ var COMPONENT_JS = `(() => {
|
|
|
8333
8340
|
this.respond(msg2.id, false, undefined, "Video capture requires the Haltija Desktop app. Run: npx haltija@latest -f");
|
|
8334
8341
|
return;
|
|
8335
8342
|
}
|
|
8336
|
-
haltija.stopVideoCapture().then((
|
|
8337
|
-
if (
|
|
8338
|
-
this.respond(msg2.id, true, { path:
|
|
8343
|
+
haltija.stopVideoCapture().then((result) => {
|
|
8344
|
+
if (result.success) {
|
|
8345
|
+
this.respond(msg2.id, true, { path: result.path, duration: result.duration, size: result.size, format: result.format });
|
|
8339
8346
|
} else {
|
|
8340
|
-
this.respond(msg2.id, false, undefined,
|
|
8347
|
+
this.respond(msg2.id, false, undefined, result.error || "Failed to stop video");
|
|
8341
8348
|
}
|
|
8342
8349
|
}).catch((err) => {
|
|
8343
8350
|
this.respond(msg2.id, false, undefined, \`Failed to stop video: \${err.message}\`);
|
|
@@ -8347,8 +8354,8 @@ var COMPONENT_JS = `(() => {
|
|
|
8347
8354
|
this.respond(msg2.id, true, { recording: false });
|
|
8348
8355
|
return;
|
|
8349
8356
|
}
|
|
8350
|
-
haltija.videoStatus().then((
|
|
8351
|
-
this.respond(msg2.id, true,
|
|
8357
|
+
haltija.videoStatus().then((result) => {
|
|
8358
|
+
this.respond(msg2.id, true, result);
|
|
8352
8359
|
}).catch(() => {
|
|
8353
8360
|
this.respond(msg2.id, true, { recording: false });
|
|
8354
8361
|
});
|
|
@@ -8365,8 +8372,8 @@ var COMPONENT_JS = `(() => {
|
|
|
8365
8372
|
this.respond(msg2.id, false, undefined, notAvailable);
|
|
8366
8373
|
return;
|
|
8367
8374
|
}
|
|
8368
|
-
haltija.networkWatch(payload2 || {}).then((
|
|
8369
|
-
this.respond(msg2.id,
|
|
8375
|
+
haltija.networkWatch(payload2 || {}).then((result) => {
|
|
8376
|
+
this.respond(msg2.id, result.success !== false, result);
|
|
8370
8377
|
}).catch((err) => {
|
|
8371
8378
|
this.respond(msg2.id, false, undefined, err.message);
|
|
8372
8379
|
});
|
|
@@ -8375,8 +8382,8 @@ var COMPONENT_JS = `(() => {
|
|
|
8375
8382
|
this.respond(msg2.id, false, undefined, notAvailable);
|
|
8376
8383
|
return;
|
|
8377
8384
|
}
|
|
8378
|
-
haltija.networkUnwatch().then((
|
|
8379
|
-
this.respond(msg2.id, true,
|
|
8385
|
+
haltija.networkUnwatch().then((result) => {
|
|
8386
|
+
this.respond(msg2.id, true, result);
|
|
8380
8387
|
}).catch((err) => {
|
|
8381
8388
|
this.respond(msg2.id, false, undefined, err.message);
|
|
8382
8389
|
});
|
|
@@ -8385,8 +8392,8 @@ var COMPONENT_JS = `(() => {
|
|
|
8385
8392
|
this.respond(msg2.id, false, undefined, notAvailable);
|
|
8386
8393
|
return;
|
|
8387
8394
|
}
|
|
8388
|
-
haltija.networkLog(payload2 || {}).then((
|
|
8389
|
-
this.respond(msg2.id, true,
|
|
8395
|
+
haltija.networkLog(payload2 || {}).then((result) => {
|
|
8396
|
+
this.respond(msg2.id, true, result);
|
|
8390
8397
|
}).catch((err) => {
|
|
8391
8398
|
this.respond(msg2.id, false, undefined, err.message);
|
|
8392
8399
|
});
|
|
@@ -8395,8 +8402,8 @@ var COMPONENT_JS = `(() => {
|
|
|
8395
8402
|
this.respond(msg2.id, false, undefined, notAvailable);
|
|
8396
8403
|
return;
|
|
8397
8404
|
}
|
|
8398
|
-
haltija.networkStats().then((
|
|
8399
|
-
this.respond(msg2.id, true,
|
|
8405
|
+
haltija.networkStats().then((result) => {
|
|
8406
|
+
this.respond(msg2.id, true, result);
|
|
8400
8407
|
}).catch((err) => {
|
|
8401
8408
|
this.respond(msg2.id, false, undefined, err.message);
|
|
8402
8409
|
});
|
|
@@ -8405,8 +8412,8 @@ var COMPONENT_JS = `(() => {
|
|
|
8405
8412
|
this.respond(msg2.id, false, undefined, notAvailable);
|
|
8406
8413
|
return;
|
|
8407
8414
|
}
|
|
8408
|
-
haltija.networkClear().then((
|
|
8409
|
-
this.respond(msg2.id, true,
|
|
8415
|
+
haltija.networkClear().then((result) => {
|
|
8416
|
+
this.respond(msg2.id, true, result);
|
|
8410
8417
|
}).catch((err) => {
|
|
8411
8418
|
this.respond(msg2.id, false, undefined, err.message);
|
|
8412
8419
|
});
|
|
@@ -8852,9 +8859,9 @@ var COMPONENT_JS = `(() => {
|
|
|
8852
8859
|
try {
|
|
8853
8860
|
const capturePromise = targetSelector ? haltija.captureElement(targetSelector) : haltija.capturePage();
|
|
8854
8861
|
const timeoutPromise = new Promise((resolve) => setTimeout(() => resolve({ success: false, error: "Screenshot capture timed out after 10s" }), 1e4));
|
|
8855
|
-
const
|
|
8856
|
-
if (
|
|
8857
|
-
const converted = await convertFormat(
|
|
8862
|
+
const result = await Promise.race([capturePromise, timeoutPromise]);
|
|
8863
|
+
if (result?.success && result.data) {
|
|
8864
|
+
const converted = await convertFormat(result.data);
|
|
8858
8865
|
this.respond(msg2.id, true, {
|
|
8859
8866
|
image: converted.image,
|
|
8860
8867
|
viewport,
|
|
@@ -8864,8 +8871,8 @@ var COMPONENT_JS = `(() => {
|
|
|
8864
8871
|
source: "electron"
|
|
8865
8872
|
});
|
|
8866
8873
|
return;
|
|
8867
|
-
} else if (
|
|
8868
|
-
this.respond(msg2.id, false, null,
|
|
8874
|
+
} else if (result && !result.success) {
|
|
8875
|
+
this.respond(msg2.id, false, null, result.error || "Electron capture failed");
|
|
8869
8876
|
return;
|
|
8870
8877
|
}
|
|
8871
8878
|
} catch (err) {
|
|
@@ -8936,15 +8943,30 @@ var COMPONENT_JS = `(() => {
|
|
|
8936
8943
|
this.respond(msg2.id, true);
|
|
8937
8944
|
}
|
|
8938
8945
|
}
|
|
8939
|
-
async handleEvalMessage(
|
|
8946
|
+
async handleEvalMessage(msg2) {
|
|
8940
8947
|
try {
|
|
8941
|
-
const result =
|
|
8948
|
+
const result = this.evalCode(msg2.payload.code);
|
|
8942
8949
|
const resolved = result instanceof Promise ? await result : result;
|
|
8943
|
-
this.respond(
|
|
8950
|
+
this.respond(msg2.id, true, resolved);
|
|
8944
8951
|
} catch (err) {
|
|
8945
|
-
this.respond(
|
|
8952
|
+
this.respond(msg2.id, false, null, err.message);
|
|
8946
8953
|
}
|
|
8947
8954
|
}
|
|
8955
|
+
evalCode(code) {
|
|
8956
|
+
try {
|
|
8957
|
+
return eval(code);
|
|
8958
|
+
} catch (err) {
|
|
8959
|
+
if (!(err instanceof SyntaxError) || !/\\b(await|return)\\b/.test(code))
|
|
8960
|
+
throw err;
|
|
8961
|
+
}
|
|
8962
|
+
try {
|
|
8963
|
+
return eval(\`(async () => (\${code}))()\`);
|
|
8964
|
+
} catch (err) {
|
|
8965
|
+
if (!(err instanceof SyntaxError))
|
|
8966
|
+
throw err;
|
|
8967
|
+
}
|
|
8968
|
+
return eval(\`(async () => { \${code} })()\`);
|
|
8969
|
+
}
|
|
8948
8970
|
async handleFetchMessage(msg2) {
|
|
8949
8971
|
const { url } = msg2.payload;
|
|
8950
8972
|
if (!url) {
|
|
@@ -9021,14 +9043,14 @@ var COMPONENT_JS = `(() => {
|
|
|
9021
9043
|
let el = null;
|
|
9022
9044
|
let targetDesc = "";
|
|
9023
9045
|
if (ref) {
|
|
9024
|
-
const
|
|
9025
|
-
el =
|
|
9046
|
+
const result = refRegistry.resolveWithStatus(ref);
|
|
9047
|
+
el = result.element;
|
|
9026
9048
|
targetDesc = \`@\${ref}\`;
|
|
9027
9049
|
if (el) {
|
|
9028
9050
|
stats.refsResolved++;
|
|
9029
9051
|
} else {
|
|
9030
9052
|
stats.refsStale++;
|
|
9031
|
-
const errorMsg =
|
|
9053
|
+
const errorMsg = result.status === "never_assigned" ? \`Ref @\${ref} was never assigned (highest ref is @\${refRegistry.getStats().highWaterMark})\` : result.status === "removed_from_dom" ? \`Ref @\${ref} points to an element that was removed from the DOM (try refreshing /tree)\` : \`Ref @\${ref} is stale - element was garbage collected (try refreshing /tree)\`;
|
|
9032
9054
|
this.respond(responseId, false, null, errorMsg);
|
|
9033
9055
|
return;
|
|
9034
9056
|
}
|
|
@@ -9373,14 +9395,14 @@ var COMPONENT_JS = `(() => {
|
|
|
9373
9395
|
let el = null;
|
|
9374
9396
|
let targetDesc = "";
|
|
9375
9397
|
if (payload2.ref) {
|
|
9376
|
-
const
|
|
9377
|
-
el =
|
|
9398
|
+
const result = refRegistry.resolveWithStatus(payload2.ref);
|
|
9399
|
+
el = result.element;
|
|
9378
9400
|
targetDesc = \`@\${payload2.ref}\`;
|
|
9379
9401
|
if (el) {
|
|
9380
9402
|
stats.refsResolved++;
|
|
9381
9403
|
} else {
|
|
9382
9404
|
stats.refsStale++;
|
|
9383
|
-
const errorMsg =
|
|
9405
|
+
const errorMsg = result.status === "never_assigned" ? \`Ref @\${payload2.ref} was never assigned (highest ref is @\${refRegistry.getStats().highWaterMark})\` : result.status === "removed_from_dom" ? \`Ref @\${payload2.ref} points to an element that was removed from the DOM (try refreshing /tree)\` : \`Ref @\${payload2.ref} is stale - element was garbage collected (try refreshing /tree)\`;
|
|
9384
9406
|
this.respond(responseId, false, null, errorMsg);
|
|
9385
9407
|
return;
|
|
9386
9408
|
}
|
|
@@ -9449,15 +9471,15 @@ var COMPONENT_JS = `(() => {
|
|
|
9449
9471
|
let target = null;
|
|
9450
9472
|
let targetDesc = "";
|
|
9451
9473
|
if (ref) {
|
|
9452
|
-
const
|
|
9453
|
-
target =
|
|
9474
|
+
const result = refRegistry.resolveWithStatus(ref);
|
|
9475
|
+
target = result.element;
|
|
9454
9476
|
targetDesc = \`@\${ref}\`;
|
|
9455
9477
|
if (target) {
|
|
9456
9478
|
stats.refsResolved++;
|
|
9457
9479
|
target.focus();
|
|
9458
9480
|
} else {
|
|
9459
9481
|
stats.refsStale++;
|
|
9460
|
-
const errorMsg =
|
|
9482
|
+
const errorMsg = result.status === "never_assigned" ? \`Ref @\${ref} was never assigned (highest ref is @\${refRegistry.getStats().highWaterMark})\` : result.status === "removed_from_dom" ? \`Ref @\${ref} points to an element that was removed from the DOM (try refreshing /tree)\` : \`Ref @\${ref} is stale - element was garbage collected (try refreshing /tree)\`;
|
|
9461
9483
|
this.respond(responseId, false, null, errorMsg);
|
|
9462
9484
|
return;
|
|
9463
9485
|
}
|
|
@@ -9849,9 +9871,9 @@ var COMPONENT_JS = `(() => {
|
|
|
9849
9871
|
});
|
|
9850
9872
|
} else if (action2 === "result") {
|
|
9851
9873
|
if (this.selectionResult) {
|
|
9852
|
-
const
|
|
9874
|
+
const result = this.selectionResult;
|
|
9853
9875
|
this.clearSelection();
|
|
9854
|
-
this.respond(msg2.id, true,
|
|
9876
|
+
this.respond(msg2.id, true, result);
|
|
9855
9877
|
} else {
|
|
9856
9878
|
this.respond(msg2.id, false, null, "No selection available");
|
|
9857
9879
|
}
|
|
@@ -11112,7 +11134,17 @@ ${isElectronApp ? "" : ` <script>
|
|
|
11112
11134
|
document.getElementById('tab-' + tabId).classList.add('active');
|
|
11113
11135
|
});
|
|
11114
11136
|
});
|
|
11115
|
-
|
|
11137
|
+
|
|
11138
|
+
// Deep-link to a tab via ?tab=<name>. Lets tests (and links) land directly
|
|
11139
|
+
// on a tab instead of relying on a click landing right after navigation \u2014
|
|
11140
|
+
// which raced under headless CI.
|
|
11141
|
+
(function() {
|
|
11142
|
+
var wanted = new URLSearchParams(location.search).get('tab');
|
|
11143
|
+
if (!wanted) return;
|
|
11144
|
+
var btn = document.querySelector('.tab[data-tab="' + wanted + '"]');
|
|
11145
|
+
if (btn) btn.click();
|
|
11146
|
+
})();
|
|
11147
|
+
|
|
11116
11148
|
// Copy button functionality
|
|
11117
11149
|
function copyCode(btn) {
|
|
11118
11150
|
var pre = btn.parentElement.querySelector('pre');
|
|
@@ -12380,7 +12412,14 @@ var eval_ = endpoint({
|
|
|
12380
12412
|
description: `Run arbitrary JavaScript in the browser context. Returns the result.
|
|
12381
12413
|
|
|
12382
12414
|
The code runs in the page's context with access to window, document, etc.
|
|
12383
|
-
Return values are JSON-serialized.
|
|
12415
|
+
Return values are JSON-serialized.
|
|
12416
|
+
|
|
12417
|
+
Async code is supported: a returned Promise is awaited, and top-level \`await\`
|
|
12418
|
+
works. Multi-statement code needs an explicit \`return\` to produce a value.
|
|
12419
|
+
|
|
12420
|
+
document.title -> the title
|
|
12421
|
+
await fetch('/api').then(r => r.json()) -> the parsed body
|
|
12422
|
+
const r = await fetch('/api'); return r.status -> the status code`,
|
|
12384
12423
|
category: "debug",
|
|
12385
12424
|
input: L.object({
|
|
12386
12425
|
code: L.string.describe("JavaScript code to execute"),
|