@poe-platform/safe-bash 0.1.704 → 0.1.705

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.
@@ -0,0 +1,35 @@
1
+ /*! Derived from @cloudflare/playwright 1.3.6 screenshotter.js; Microsoft Corporation; Apache-2.0. */
2
+ async function waitForBrowserScreenshotSize(frame, progress, expression) {
3
+ return frame.retryWithProgressAndTimeouts(progress, [100], async (continuePolling) => {
4
+ const result = await progress.race(frame.evaluateExpression(expression, { isFunction: true, world: 'utility' }));
5
+ return result || continuePolling;
6
+ });
7
+ }
8
+ export const browserScreenshotMethods = ({ async _preparePageForScreenshot(progress, frame, screenshotStyle, hideCaret, disableAnimations) {
9
+ if (disableAnimations)
10
+ progress.log(" disabled all CSS animations");
11
+ const syncAnimations = this._page.delegate.shouldToggleStyleSheetToSyncAnimations();
12
+ const script = `((__name => (${"function inPagePrepareForScreenshots(screenshotStyle, hideCaret, disableAnimations, syncAnimations) {\n if (syncAnimations) {\n const style = document.createElement(\"style\");\n style.textContent = \"body {}\";\n document.head.appendChild(style);\n document.documentElement.getBoundingClientRect();\n style.remove();\n }\n if (!screenshotStyle && !hideCaret && !disableAnimations)\n return;\n const collectRoots = (root, roots2 = []) => {\n roots2.push(root);\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);\n do {\n const node = walker.currentNode;\n const shadowRoot = node instanceof Element ? node.shadowRoot : null;\n if (shadowRoot)\n collectRoots(shadowRoot, roots2);\n } while (walker.nextNode());\n return roots2;\n };\n const roots = collectRoots(document);\n const cleanupCallbacks = [];\n if (screenshotStyle) {\n for (const root of roots) {\n const styleTag = document.createElement(\"style\");\n styleTag.textContent = screenshotStyle;\n if (root === document)\n document.documentElement.append(styleTag);\n else\n root.append(styleTag);\n cleanupCallbacks.push(() => {\n styleTag.remove();\n });\n }\n }\n if (hideCaret) {\n const elements = /* @__PURE__ */ new Map();\n for (const root of roots) {\n root.querySelectorAll(\"input,textarea,[contenteditable]\").forEach((element) => {\n elements.set(element, {\n value: element.style.getPropertyValue(\"caret-color\"),\n priority: element.style.getPropertyPriority(\"caret-color\")\n });\n element.style.setProperty(\"caret-color\", \"transparent\", \"important\");\n });\n }\n cleanupCallbacks.push(() => {\n for (const [element, value] of elements)\n element.style.setProperty(\"caret-color\", value.value, value.priority);\n });\n }\n if (disableAnimations) {\n const infiniteAnimationsToResume = /* @__PURE__ */ new Set();\n const handleAnimations = (root) => {\n for (const animation of root.getAnimations()) {\n if (!animation.effect || animation.playbackRate === 0 || infiniteAnimationsToResume.has(animation))\n continue;\n const endTime = animation.effect.getComputedTiming().endTime;\n if (Number.isFinite(endTime)) {\n try {\n animation.finish();\n } catch (e) {\n }\n } else {\n try {\n animation.cancel();\n infiniteAnimationsToResume.add(animation);\n } catch (e) {\n }\n }\n }\n };\n for (const root of roots) {\n const handleRootAnimations = handleAnimations.bind(null, root);\n handleRootAnimations();\n root.addEventListener(\"transitionrun\", handleRootAnimations);\n root.addEventListener(\"animationstart\", handleRootAnimations);\n cleanupCallbacks.push(() => {\n root.removeEventListener(\"transitionrun\", handleRootAnimations);\n root.removeEventListener(\"animationstart\", handleRootAnimations);\n });\n }\n cleanupCallbacks.push(() => {\n for (const animation of infiniteAnimationsToResume) {\n try {\n animation.play();\n } catch (e) {\n }\n }\n });\n }\n window.__pwCleanupScreenshot = () => {\n for (const cleanupCallback of cleanupCallbacks)\n cleanupCallback();\n delete window.__pwCleanupScreenshot;\n };\n}"}))(t => t))`;
13
+ await progress.race(this._page.safeNonStallingEvaluateInAllFrames("(" + script + `)(${JSON.stringify(screenshotStyle)}, ${hideCaret}, ${disableAnimations}, ${syncAnimations})`, "utility"));
14
+ try {
15
+ if (!process.env.PW_TEST_SCREENSHOT_NO_FONTS_READY) {
16
+ progress.log("waiting for fonts to load...");
17
+ await progress.race(frame.nonStallingEvaluateInExistingContext("document.fonts.ready", "utility").catch(() => {
18
+ }));
19
+ progress.log("fonts loaded");
20
+ }
21
+ }
22
+ catch (error) {
23
+ await this._restorePageAfterScreenshot();
24
+ throw error;
25
+ }
26
+ }, async _originalViewportSize(progress) {
27
+ let viewportSize = this._page.emulatedSize()?.viewport;
28
+ if (!viewportSize)
29
+ viewportSize = await waitForBrowserScreenshotSize(this._page.mainFrame(), progress, "() => ({ width: window.innerWidth, height: window.innerHeight })");
30
+ return viewportSize;
31
+ }, async _fullPageSize(progress) {
32
+ const fullPageSize = await waitForBrowserScreenshotSize(this._page.mainFrame(), progress, "() => {\n if (!document.body || !document.documentElement)\n return null;\n return {\n width: Math.max(\n document.body.scrollWidth,\n document.documentElement.scrollWidth,\n document.body.offsetWidth,\n document.documentElement.offsetWidth,\n document.body.clientWidth,\n document.documentElement.clientWidth\n ),\n height: Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight,\n document.body.offsetHeight,\n document.documentElement.offsetHeight,\n document.body.clientHeight,\n document.documentElement.clientHeight\n )\n };\n }");
33
+ return fullPageSize;
34
+ } });
35
+ export const prepareBrowserScreenshot = browserScreenshotMethods._preparePageForScreenshot;
@@ -0,0 +1,7 @@
1
+ import { browserScreenshotMethods } from './browser-screenshot.generated.js';
2
+ /** The pinned Worker provider owns its screenshotter locally, like its tracing server. */
3
+ export function prepareBrowserScreenshots(page) {
4
+ const bridge = page;
5
+ const native = bridge._connection.toImpl(page);
6
+ Object.assign(native.screenshotter, browserScreenshotMethods);
7
+ }
@@ -5,6 +5,7 @@ import { captureBrowserSnapshotJSON } from "./browser-snapshot-json.js";
5
5
  import { captureBrowserTrace } from "./browser-trace.js";
6
6
  import { acquireCloudflareBrowser } from "./shell-browser-resource.js";
7
7
  import { browserProfileRuntime } from './browser-profile-runtime.js';
8
+ import { prepareBrowserScreenshots } from './browser-screenshot.js';
8
9
  export function createCloudflarePlaywrightAdapter(binding, profiles, runtime, limits = { maxStorageBytes: 2 * 1024 * 1024 }) {
9
10
  if (!Number.isSafeInteger(limits.maxStorageBytes) || limits.maxStorageBytes < 1)
10
11
  throw new TypeError('Invalid Cloudflare storage byte limit');
@@ -88,6 +89,9 @@ function publicBrowser(browser) {
88
89
  // The acquired portable lease restores origins through held private targets.
89
90
  const { storageState: ignoredStorageState, ...contextOptions } = options ?? {};
90
91
  const context = await browser.newContext(contextOptions);
92
+ context.on('page', prepareBrowserScreenshots);
93
+ for (const page of context.pages())
94
+ prepareBrowserScreenshots(page);
91
95
  Object.defineProperty(context, 'browserProfile', { value: browserProfileRuntime(browser, context) });
92
96
  const acquireCDP = context.newCDPSession.bind(context);
93
97
  return Object.assign(context, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poe-platform/safe-bash",
3
- "version": "0.1.704",
3
+ "version": "0.1.705",
4
4
  "description": "Extensible virtual shell with pluggable filesystems and streaming commands",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -378,7 +378,7 @@
378
378
  "access": "public"
379
379
  },
380
380
  "dependencies": {
381
- "@poe-platform/safe-fs": "0.1.704",
381
+ "@poe-platform/safe-fs": "0.1.705",
382
382
  "pako": "3.0.1",
383
383
  "@types/node": "^25.2.2",
384
384
  "@noble/hashes": "2.4.0",