feat(coding-agent-tools): implemented browser execution safety controls
- Implemented cell budget clamping for timeouts to prevent stalled browser operations from exceeding execution limits. - Added `recover` capabilities for tab workers to clear blocking dialogs and safely terminate hung navigations. - Introduced `//!world=main` support for `tab.evaluate` via Puppeteer patch to allow execution in main execution contexts. - Improved failure attribution for tab terminations by tracking dialogs, stalled operations, and specific termination reasons.
This commit is contained in:
@@ -1,16 +1,24 @@
|
||||
diff --git a/node_modules/puppeteer-core/.bun-tag-2e714b457f0bd8e8 b/.bun-tag-2e714b457f0bd8e8
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
|
||||
diff --git a/node_modules/puppeteer-core/.bun-tag-a797aeb3ca2bd69f b/.bun-tag-a797aeb3ca2bd69f
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
|
||||
diff --git a/lib/puppeteer/api/ElementHandle.js b/lib/puppeteer/api/ElementHandle.js
|
||||
index 81454fe2af73518f7e76f04cbe3a7f170d735fa5..6f9eedb9fc1344901705bc83cb3cf415e6271e28 100644
|
||||
index 81454fe2af73518f7e76f04cbe3a7f170d735fa5..ee6b042c87861f00d7fcbb6e3eb6e87af232ebbd 100644
|
||||
--- a/lib/puppeteer/api/ElementHandle.js
|
||||
+++ b/lib/puppeteer/api/ElementHandle.js
|
||||
@@ -102,6 +102,31 @@ import { throwIfDisposed } from '../util/decorators.js';
|
||||
@@ -102,6 +102,36 @@ import { throwIfDisposed } from '../util/decorators.js';
|
||||
import { _isElementHandle } from './ElementHandleSymbol.js';
|
||||
import { JSHandle } from './JSHandle.js';
|
||||
import { NodeLocator } from './locators/locators.js';
|
||||
+const MAIN_WORLD_DIRECTIVE = /^\s*(?:(?:\/\/!world=main(?=$|\s))|(?:\/\*!world=main\s*\*\/))/;
|
||||
+const shouldEvaluateInMainWorld = (pageFunction) => {
|
||||
+ if (pageFunction instanceof String) {
|
||||
+ // withSourcePuppeteerURLIfNone tags string page functions via Object.assign,
|
||||
+ // which boxes the primitive; unbox so the directive check still sees a string.
|
||||
+ pageFunction = pageFunction.toString();
|
||||
+ }
|
||||
+ if (typeof pageFunction !== 'function' && typeof pageFunction !== 'string') {
|
||||
+ return false;
|
||||
+ }
|
||||
@@ -33,11 +41,11 @@ index 81454fe2af73518f7e76f04cbe3a7f170d735fa5..6f9eedb9fc1344901705bc83cb3cf415
|
||||
+ const arrowIndex = source.indexOf('=>');
|
||||
+ const bodyStart = source.indexOf('{', arrowIndex >= 0 ? arrowIndex : 0);
|
||||
+ return bodyStart >= 0 && MAIN_WORLD_DIRECTIVE.test(source.slice(bodyStart + 1));
|
||||
+};
|
||||
+}
|
||||
/**
|
||||
* A given method will have it's `this` replaced with an isolated version of
|
||||
* `this` when decorated with this decorator.
|
||||
@@ -299,6 +324,7 @@ let ElementHandle = (() => {
|
||||
@@ -299,6 +329,7 @@ let ElementHandle = (() => {
|
||||
* trying to adopt it multiple times
|
||||
*/
|
||||
isolatedHandle = __runInitializers(this, _instanceExtraInitializers);
|
||||
@@ -45,7 +53,7 @@ index 81454fe2af73518f7e76f04cbe3a7f170d735fa5..6f9eedb9fc1344901705bc83cb3cf415
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@@ -335,19 +361,37 @@ let ElementHandle = (() => {
|
||||
@@ -335,19 +366,37 @@ let ElementHandle = (() => {
|
||||
async getProperties() {
|
||||
return await this.handle.getProperties();
|
||||
}
|
||||
@@ -85,7 +93,7 @@ index 81454fe2af73518f7e76f04cbe3a7f170d735fa5..6f9eedb9fc1344901705bc83cb3cf415
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
@@ -371,7 +415,7 @@ let ElementHandle = (() => {
|
||||
@@ -371,7 +420,7 @@ let ElementHandle = (() => {
|
||||
* @internal
|
||||
*/
|
||||
async dispose() {
|
||||
@@ -94,7 +102,7 @@ index 81454fe2af73518f7e76f04cbe3a7f170d735fa5..6f9eedb9fc1344901705bc83cb3cf415
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
@@ -555,15 +599,27 @@ let ElementHandle = (() => {
|
||||
@@ -555,15 +604,27 @@ let ElementHandle = (() => {
|
||||
async $$eval(selector, pageFunction, ...args) {
|
||||
const env_2 = { stack: [], error: void 0, hasError: false };
|
||||
try {
|
||||
@@ -127,15 +135,20 @@ index 81454fe2af73518f7e76f04cbe3a7f170d735fa5..6f9eedb9fc1344901705bc83cb3cf415
|
||||
]);
|
||||
return result;
|
||||
diff --git a/lib/puppeteer/api/Frame.js b/lib/puppeteer/api/Frame.js
|
||||
index 8698d2a5a976b277344fe42e90ffe985bdf0fbd7..01614143cba96055d0f0c22a1eb903d4265ca15f 100644
|
||||
index 8698d2a5a976b277344fe42e90ffe985bdf0fbd7..62c3b7ca8ec987cc62ceacec69acf6545bb59b86 100644
|
||||
--- a/lib/puppeteer/api/Frame.js
|
||||
+++ b/lib/puppeteer/api/Frame.js
|
||||
@@ -119,6 +119,31 @@ export var FrameEvent;
|
||||
@@ -119,6 +119,36 @@ export var FrameEvent;
|
||||
export const throwIfDetached = throwIfDisposed(frame => {
|
||||
return `Attempted to use detached Frame '${frame._id}'.`;
|
||||
});
|
||||
+const MAIN_WORLD_DIRECTIVE = /^\s*(?:(?:\/\/!world=main(?=$|\s))|(?:\/\*!world=main\s*\*\/))/;
|
||||
+const shouldEvaluateInMainWorld = (pageFunction) => {
|
||||
+ if (pageFunction instanceof String) {
|
||||
+ // withSourcePuppeteerURLIfNone tags string page functions via Object.assign,
|
||||
+ // which boxes the primitive; unbox so the directive check still sees a string.
|
||||
+ pageFunction = pageFunction.toString();
|
||||
+ }
|
||||
+ if (typeof pageFunction !== 'function' && typeof pageFunction !== 'string') {
|
||||
+ return false;
|
||||
+ }
|
||||
@@ -158,11 +171,11 @@ index 8698d2a5a976b277344fe42e90ffe985bdf0fbd7..01614143cba96055d0f0c22a1eb903d4
|
||||
+ const arrowIndex = source.indexOf('=>');
|
||||
+ const bodyStart = source.indexOf('{', arrowIndex >= 0 ? arrowIndex : 0);
|
||||
+ return bodyStart >= 0 && MAIN_WORLD_DIRECTIVE.test(source.slice(bodyStart + 1));
|
||||
+};
|
||||
+}
|
||||
/**
|
||||
* Represents a DOM frame.
|
||||
*
|
||||
@@ -277,12 +302,21 @@ let Frame = (() => {
|
||||
@@ -277,12 +307,21 @@ let Frame = (() => {
|
||||
super();
|
||||
}
|
||||
#_document;
|
||||
@@ -186,7 +199,7 @@ index 8698d2a5a976b277344fe42e90ffe985bdf0fbd7..01614143cba96055d0f0c22a1eb903d4
|
||||
return document;
|
||||
});
|
||||
}
|
||||
@@ -295,6 +329,7 @@ let Frame = (() => {
|
||||
@@ -295,6 +334,7 @@ let Frame = (() => {
|
||||
*/
|
||||
clearDocumentHandle() {
|
||||
this.#_document = undefined;
|
||||
@@ -194,7 +207,7 @@ index 8698d2a5a976b277344fe42e90ffe985bdf0fbd7..01614143cba96055d0f0c22a1eb903d4
|
||||
}
|
||||
/**
|
||||
* @returns The frame element associated with this frame (if any).
|
||||
@@ -345,8 +380,9 @@ let Frame = (() => {
|
||||
@@ -345,8 +385,9 @@ let Frame = (() => {
|
||||
* See {@link Page.evaluateHandle} for details.
|
||||
*/
|
||||
async evaluateHandle(pageFunction, ...args) {
|
||||
@@ -205,7 +218,7 @@ index 8698d2a5a976b277344fe42e90ffe985bdf0fbd7..01614143cba96055d0f0c22a1eb903d4
|
||||
}
|
||||
/**
|
||||
* Behaves identically to {@link Page.evaluate} except it's run within
|
||||
@@ -355,8 +391,9 @@ let Frame = (() => {
|
||||
@@ -355,8 +396,9 @@ let Frame = (() => {
|
||||
* See {@link Page.evaluate} for details.
|
||||
*/
|
||||
async evaluate(pageFunction, ...args) {
|
||||
@@ -216,7 +229,7 @@ index 8698d2a5a976b277344fe42e90ffe985bdf0fbd7..01614143cba96055d0f0c22a1eb903d4
|
||||
}
|
||||
/**
|
||||
* @internal
|
||||
@@ -458,9 +495,10 @@ let Frame = (() => {
|
||||
@@ -458,9 +500,10 @@ let Frame = (() => {
|
||||
* @returns A promise to the result of the function.
|
||||
*/
|
||||
async $eval(selector, pageFunction, ...args) {
|
||||
@@ -228,7 +241,7 @@ index 8698d2a5a976b277344fe42e90ffe985bdf0fbd7..01614143cba96055d0f0c22a1eb903d4
|
||||
return await document.$eval(selector, pageFunction, ...args);
|
||||
}
|
||||
/**
|
||||
@@ -498,9 +536,10 @@ let Frame = (() => {
|
||||
@@ -498,9 +541,10 @@ let Frame = (() => {
|
||||
* @returns A promise to the result of the function.
|
||||
*/
|
||||
async $$eval(selector, pageFunction, ...args) {
|
||||
@@ -240,7 +253,7 @@ index 8698d2a5a976b277344fe42e90ffe985bdf0fbd7..01614143cba96055d0f0c22a1eb903d4
|
||||
return await document.$$eval(selector, pageFunction, ...args);
|
||||
}
|
||||
/**
|
||||
@@ -577,7 +616,8 @@ let Frame = (() => {
|
||||
@@ -577,7 +621,8 @@ let Frame = (() => {
|
||||
* @returns the promise which resolve when the `pageFunction` returns a truthy value.
|
||||
*/
|
||||
async waitForFunction(pageFunction, options = {}, ...args) {
|
||||
|
||||
Reference in New Issue
Block a user