@skrillex1224/playwright-toolkit 2.1.202 → 2.1.203

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/dist/index.cjs CHANGED
@@ -3067,6 +3067,7 @@ var Captcha = {
3067
3067
  };
3068
3068
 
3069
3069
  // src/mutation.js
3070
+ var import_node_crypto = require("node:crypto");
3070
3071
  var import_uuid2 = require("uuid");
3071
3072
  var logger10 = createInternalLogger("Mutation");
3072
3073
  var MUTATION_MONITOR_MODE = Object.freeze({
@@ -3273,82 +3274,138 @@ var Mutation = {
3273
3274
  if (text.length <= max) return text;
3274
3275
  return `${text.slice(0, max)}...`;
3275
3276
  };
3277
+ const normalizeText = (value) => String(value || "").replace(/\s+/g, " ").trim();
3278
+ const normalizeHtml = (value) => String(value || "").trim();
3279
+ const hashSnapshot = (value) => (0, import_node_crypto.createHash)("sha256").update(String(value || "")).digest("hex");
3276
3280
  const buildState = async () => {
3277
- return await page.evaluate(({ selectorList: selectorList2 }) => {
3278
- const normalizeText = (value) => String(value || "").replace(/\s+/g, " ").trim();
3279
- const tail = (value, max = 512) => {
3280
- const text = String(value || "");
3281
- if (text.length <= max) return text;
3282
- return text.slice(text.length - max);
3283
- };
3284
- const safeFrameId = (frameEl) => {
3285
- const id = String(frameEl?.id || "").trim();
3286
- if (id) return id;
3287
- const name = String(frameEl?.name || "").trim();
3288
- if (name) return name;
3289
- return "no-id";
3290
- };
3291
- const items = [];
3292
- selectorList2.forEach((selector) => {
3293
- let nodes = [];
3281
+ const items = [];
3282
+ const describeElement = async (elementHandle) => {
3283
+ return await elementHandle.evaluate((node) => {
3284
+ const tagName = String(node?.tagName || "").toUpperCase();
3285
+ return {
3286
+ tagName,
3287
+ id: String(node?.id || "").trim(),
3288
+ name: String(node?.getAttribute?.("name") || "").trim()
3289
+ };
3290
+ });
3291
+ };
3292
+ const readElementSnapshot = async (elementHandle) => {
3293
+ return await elementHandle.evaluate((node) => {
3294
+ const text = String(node?.innerText || node?.textContent || "");
3295
+ const html = String(node?.innerHTML || node?.outerHTML || "");
3296
+ return {
3297
+ text,
3298
+ html
3299
+ };
3300
+ });
3301
+ };
3302
+ const readFrameSnapshot = async (frame) => {
3303
+ return await frame.evaluate(() => {
3304
+ const root = document.documentElement || document.body;
3305
+ const text = String(root?.innerText || root?.textContent || "");
3306
+ const html = String(root?.innerHTML || "");
3307
+ return {
3308
+ text,
3309
+ html,
3310
+ url: window.location.href,
3311
+ readyState: document.readyState
3312
+ };
3313
+ });
3314
+ };
3315
+ for (const selector of selectorList) {
3316
+ let handles = [];
3317
+ try {
3318
+ handles = await page.locator(selector).elementHandles();
3319
+ } catch {
3320
+ continue;
3321
+ }
3322
+ for (let index = 0; index < handles.length; index += 1) {
3323
+ const handle = handles[index];
3294
3324
  try {
3295
- nodes = Array.from(document.querySelectorAll(selector));
3296
- } catch {
3297
- return;
3298
- }
3299
- nodes.forEach((node, index) => {
3300
- const isIframe = node?.tagName === "IFRAME";
3301
- let text = "";
3302
- let html = "";
3325
+ const descriptor = await describeElement(handle);
3326
+ const tagName = descriptor?.tagName || "";
3327
+ const isFrameElement = tagName === "IFRAME" || tagName === "FRAME";
3328
+ const nodeName = descriptor?.id || descriptor?.name || "no-id";
3303
3329
  let source = "main";
3304
3330
  let path2 = `${selector}[${index}]`;
3305
- if (isIframe) {
3331
+ let text = "";
3332
+ let html = "";
3333
+ let frameUrl = "";
3334
+ let readyState = "";
3335
+ if (isFrameElement) {
3306
3336
  source = "iframe";
3307
- path2 = `${selector}[${index}]::iframe(${safeFrameId(node)})`;
3308
- try {
3309
- const frameDoc = node.contentDocument;
3310
- const frameRoot = frameDoc?.body || frameDoc?.documentElement;
3311
- if (frameRoot) {
3312
- text = normalizeText(frameRoot.innerText || frameRoot.textContent || "");
3313
- html = normalizeText(frameRoot.innerHTML || "");
3337
+ path2 = `${selector}[${index}]::iframe(${nodeName})`;
3338
+ const frame = await handle.contentFrame();
3339
+ if (frame) {
3340
+ try {
3341
+ const frameSnapshot = await readFrameSnapshot(frame);
3342
+ text = normalizeText(frameSnapshot?.text || "");
3343
+ html = normalizeHtml(frameSnapshot?.html || "");
3344
+ frameUrl = String(frameSnapshot?.url || "").trim();
3345
+ readyState = String(frameSnapshot?.readyState || "").trim();
3346
+ } catch (error) {
3347
+ source = "iframe-unreadable";
3348
+ readyState = error?.name || "unreadable";
3314
3349
  }
3315
- } catch {
3350
+ } else {
3351
+ source = "iframe-detached";
3316
3352
  }
3317
3353
  } else {
3318
- text = normalizeText(node?.innerText || node?.textContent || "");
3319
- html = normalizeText(node?.innerHTML || node?.outerHTML || "");
3354
+ try {
3355
+ const elementSnapshot = await readElementSnapshot(handle);
3356
+ text = normalizeText(elementSnapshot?.text || "");
3357
+ html = normalizeHtml(elementSnapshot?.html || "");
3358
+ } catch (error) {
3359
+ source = "main-unreadable";
3360
+ readyState = error?.name || "unreadable";
3361
+ }
3320
3362
  }
3321
- const snapshot = text || html;
3363
+ const snapshot = `${text}
3364
+ <!--HTML-->
3365
+ ${html}`;
3322
3366
  items.push({
3323
3367
  selector,
3324
3368
  source,
3325
3369
  path: path2,
3326
3370
  text,
3327
3371
  html,
3372
+ frameUrl,
3373
+ readyState,
3328
3374
  snapshot
3329
3375
  });
3330
- });
3331
- });
3332
- const snapshotKey = items.map((item) => `${item.path}:${item.snapshot.length}:${tail(item.snapshot, 512)}`).join("||");
3333
- const summaryText = items.map((item) => item.snapshot || item.text).join("\n").trim();
3334
- const summaryHtml = items.map((item) => item.html).join("\n");
3335
- const hasMatched = items.length > 0;
3336
- const primary = items.length > 0 ? items[items.length - 1] : null;
3337
- return {
3338
- hasMatched,
3339
- snapshotKey,
3340
- text: summaryText,
3341
- html: summaryHtml,
3342
- snapshotLength: summaryText.length,
3343
- itemCount: items.length,
3344
- primaryPath: primary?.path || "",
3345
- mutationNodes: items.map((item) => ({
3346
- html: item.html,
3347
- text: item.snapshot || item.text,
3348
- mutationType: item.source
3349
- }))
3350
- };
3351
- }, { selectorList });
3376
+ } finally {
3377
+ await handle.dispose().catch(() => {
3378
+ });
3379
+ }
3380
+ }
3381
+ }
3382
+ const serializedSnapshot = items.map((item) => JSON.stringify({
3383
+ path: item.path,
3384
+ source: item.source,
3385
+ frameUrl: item.frameUrl,
3386
+ readyState: item.readyState,
3387
+ snapshot: item.snapshot
3388
+ })).join("||");
3389
+ const summaryText = items.map((item) => item.text).join("\n").trim();
3390
+ const summaryHtml = items.map((item) => item.html).join("\n");
3391
+ const hasMatched = items.length > 0;
3392
+ const primary = items.length > 0 ? items[items.length - 1] : null;
3393
+ return {
3394
+ hasMatched,
3395
+ snapshotKey: hashSnapshot(serializedSnapshot),
3396
+ text: summaryText,
3397
+ html: summaryHtml,
3398
+ snapshotLength: serializedSnapshot.length,
3399
+ itemCount: items.length,
3400
+ primaryPath: primary?.path || "",
3401
+ mutationNodes: items.map((item) => ({
3402
+ html: item.html,
3403
+ text: item.text,
3404
+ mutationType: item.source,
3405
+ frameUrl: item.frameUrl,
3406
+ readyState: item.readyState
3407
+ }))
3408
+ };
3352
3409
  };
3353
3410
  const invokeMutationCallback = async (context) => {
3354
3411
  if (!onMutation) return "__CONTINUE__";