@skrillex1224/playwright-toolkit 3.0.9 → 3.0.11

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.js CHANGED
@@ -1059,7 +1059,7 @@ import { serializeError as serializeError2 } from "serialize-error";
1059
1059
 
1060
1060
  // src/internals/proxy-meter-runtime.js
1061
1061
  import { spawn, spawnSync } from "child_process";
1062
- import { createWriteStream, existsSync, mkdirSync, readFileSync, rmSync } from "fs";
1062
+ import { existsSync, mkdirSync, readFileSync, rmSync } from "fs";
1063
1063
  import { tmpdir } from "os";
1064
1064
  import path from "path";
1065
1065
  import { fileURLToPath } from "url";
@@ -1168,18 +1168,6 @@ var ensureLogPath = () => {
1168
1168
  const label = runId ? `proxy-meter-${runId}-${suffix}.json` : `proxy-meter-${process.pid}-${suffix}.json`;
1169
1169
  return path.join(baseDir, label);
1170
1170
  };
1171
- var ensureStdioLogPath = (logPath) => `${logPath}.stdio.log`;
1172
- var writeChildOutput = (stream, output, prefix) => {
1173
- if (!stream || !output) return;
1174
- output.on("data", (chunk) => {
1175
- const text = chunk?.toString?.() || String(chunk || "");
1176
- if (!text) return;
1177
- for (const line of text.split(/\r?\n/)) {
1178
- if (!line) continue;
1179
- stream.write(`[${(/* @__PURE__ */ new Date()).toISOString()}] ${prefix} ${line}\n`);
1180
- }
1181
- });
1182
- };
1183
1171
  var readSnapshot = (logPath) => {
1184
1172
  if (!logPath || !existsSync(logPath)) return null;
1185
1173
  try {
@@ -1347,7 +1335,6 @@ var startProxyMeter = (options = {}) => {
1347
1335
  observedDomainResourceTypes = /* @__PURE__ */ new Map();
1348
1336
  const port = pickFreePort();
1349
1337
  const logPath = ensureLogPath();
1350
- const stdioLogPath = ensureStdioLogPath(logPath);
1351
1338
  const scriptPath = resolveScriptPath();
1352
1339
  const debugMode = Boolean(options.debugMode);
1353
1340
  const debugMaxEvents = Math.max(10, toSafeInt(options.debugMaxEvents) || DEFAULT_DEBUG_MAX_EVENTS);
@@ -1360,26 +1347,19 @@ var startProxyMeter = (options = {}) => {
1360
1347
  PROXY_METER_DEBUG: debugMode ? "1" : "0",
1361
1348
  PROXY_METER_DEBUG_MAX_EVENTS: String(debugMaxEvents)
1362
1349
  };
1363
- const stdioLog = createWriteStream(stdioLogPath, { flags: "a" });
1364
- stdioLog.write(`[${(/* @__PURE__ */ new Date()).toISOString()}] [proxy-meter-runtime] start script=${scriptPath} port=${port} snapshot=${logPath}\n`);
1365
1350
  const child = spawn(process.execPath, [scriptPath], {
1366
1351
  env,
1367
- stdio: ["ignore", "pipe", "pipe"]
1352
+ stdio: ["ignore", "ignore", "ignore"]
1368
1353
  });
1369
- writeChildOutput(stdioLog, child.stdout, "stdout");
1370
- writeChildOutput(stdioLog, child.stderr, "stderr");
1371
- child.once("exit", (code, signal) => {
1372
- stdioLog.write(`[${(/* @__PURE__ */ new Date()).toISOString()}] [proxy-meter-runtime] exit code=${code ?? ""} signal=${signal ?? ""}\n`);
1373
- stdioLog.end();
1354
+ child.once("exit", (code) => {
1374
1355
  if (code && code !== 0) {
1375
- logger2.warn(`[proxy-meter] exited with code ${code}; stdio=${stdioLogPath}`);
1356
+ logger2.warn(`[proxy-meter] exited with code ${code}`);
1376
1357
  }
1377
1358
  });
1378
1359
  runtime = {
1379
1360
  proc: child,
1380
1361
  port,
1381
1362
  logPath,
1382
- stdioLogPath,
1383
1363
  startedAt: Date.now()
1384
1364
  };
1385
1365
  registerCleanup();
@@ -5603,9 +5583,6 @@ var LiveView = {
5603
5583
  useLiveView
5604
5584
  };
5605
5585
 
5606
- // src/chaptcha.js
5607
- import { v4 as uuidv4 } from "uuid";
5608
-
5609
5586
  // src/internals/captcha/bytedance.js
5610
5587
  import { mkdir, writeFile } from "fs/promises";
5611
5588
  import path2 from "path";
@@ -6264,6 +6241,9 @@ var sloveCaptcha = solveCaptcha;
6264
6241
 
6265
6242
  // src/chaptcha.js
6266
6243
  var logger12 = createInternalLogger("Captcha");
6244
+ var DOM_MONITOR_WAIT_TIMEOUT_MS = 1e3;
6245
+ var DOM_MONITOR_POST_DETECT_HIDDEN_WAIT_MS = 300;
6246
+ var DOM_MONITOR_RECOVERY_WAIT_MS = 100;
6267
6247
  var DEFAULT_CAPTCHA_RECOGNITION_OPTIONS = Object.freeze({
6268
6248
  token: "eKJvBfwfN0YRav0-VD_44E2VBSfm7l0YtddUQ7cFySI",
6269
6249
  apiUrl: "https://api.jfbym.com/api/YmServer/customApi"
@@ -6284,6 +6264,15 @@ var mergeDefinedOptions = (...sources) => {
6284
6264
  }
6285
6265
  return merged;
6286
6266
  };
6267
+ var sleep = (ms) => new Promise((resolve) => {
6268
+ setTimeout(resolve, ms);
6269
+ });
6270
+ var getErrorMessage = (error) => String(error?.message || error || "");
6271
+ var isTimeoutError = (error) => error?.name === "TimeoutError" || getErrorMessage(error).includes("Timeout");
6272
+ var isPageLifecycleError = (error) => {
6273
+ const message = getErrorMessage(error);
6274
+ return message.includes("Execution context was destroyed") || message.includes("Frame was detached") || message.includes("Target page, context or browser has been closed") || message.includes("Target closed") || message.includes("Most likely the page has been closed");
6275
+ };
6287
6276
  function useCaptchaMonitor(page, options) {
6288
6277
  const { domSelector, urlPattern, onDetected } = options;
6289
6278
  if (!domSelector && !urlPattern) {
@@ -6295,10 +6284,13 @@ function useCaptchaMonitor(page, options) {
6295
6284
  let isStopped = false;
6296
6285
  let isHandling = false;
6297
6286
  let frameHandler = null;
6298
- let exposedFunctionName = null;
6287
+ let domMonitorTask = null;
6288
+ let lastTriggeredAt = 0;
6299
6289
  const triggerDetected = async () => {
6300
- if (isStopped || isHandling) return;
6290
+ const now = Date.now();
6291
+ if (isStopped || isHandling || now - lastTriggeredAt < 250) return;
6301
6292
  isHandling = true;
6293
+ lastTriggeredAt = now;
6302
6294
  try {
6303
6295
  await onDetected();
6304
6296
  } finally {
@@ -6307,60 +6299,38 @@ function useCaptchaMonitor(page, options) {
6307
6299
  };
6308
6300
  const cleanupFns = [];
6309
6301
  if (domSelector) {
6310
- exposedFunctionName = `__c_d_${uuidv4().replace(/-/g, "_")}`;
6311
- const cleanerName = `__c_cleaner_${uuidv4().replace(/-/g, "_")}`;
6312
- page.exposeFunction(exposedFunctionName, triggerDetected).catch(() => {
6313
- });
6314
- page.addInitScript(({ selector, callbackName, cleanerName: cleanupName }) => {
6315
- (() => {
6316
- let observer = null;
6317
- const checkAndReport = () => {
6318
- const element = document.querySelector(selector);
6319
- if (!element) {
6320
- return false;
6321
- }
6322
- if (window[callbackName]) {
6323
- window[callbackName]();
6324
- }
6325
- return true;
6326
- };
6327
- checkAndReport();
6328
- observer = new MutationObserver((mutations) => {
6329
- const shouldCheck = mutations.some((mutation) => mutation.addedNodes.length > 0);
6330
- if (shouldCheck && observer) {
6331
- checkAndReport();
6332
- }
6333
- });
6334
- const mountObserver = () => {
6335
- const target = document.documentElement;
6336
- if (target && observer) {
6337
- observer.observe(target, { childList: true, subtree: true });
6302
+ domMonitorTask = (async () => {
6303
+ const locator = page.locator(domSelector).first();
6304
+ while (!isStopped) {
6305
+ try {
6306
+ await locator.waitFor({ state: "visible", timeout: DOM_MONITOR_WAIT_TIMEOUT_MS });
6307
+ if (isStopped) break;
6308
+ await triggerDetected();
6309
+ if (isStopped) break;
6310
+ await locator.waitFor({
6311
+ state: "hidden",
6312
+ timeout: DOM_MONITOR_POST_DETECT_HIDDEN_WAIT_MS
6313
+ }).catch(() => {
6314
+ });
6315
+ } catch (error) {
6316
+ if (isStopped) break;
6317
+ if (page?.isClosed?.() && isPageLifecycleError(error)) break;
6318
+ if (isTimeoutError(error) || isPageLifecycleError(error)) {
6319
+ await sleep(DOM_MONITOR_RECOVERY_WAIT_MS);
6320
+ continue;
6338
6321
  }
6339
- };
6340
- if (document.readyState === "loading") {
6341
- window.addEventListener("DOMContentLoaded", mountObserver);
6342
- } else {
6343
- mountObserver();
6322
+ logger12.warning(
6323
+ "useCaptchaMonitor",
6324
+ `DOM \u76D1\u63A7\u51FA\u73B0\u5F02\u5E38\uFF08\u7EE7\u7EED\u91CD\u8BD5\uFF09: selector=${domSelector}, error=${getErrorMessage(error)}`
6325
+ );
6326
+ await sleep(DOM_MONITOR_RECOVERY_WAIT_MS);
6344
6327
  }
6345
- window[cleanupName] = () => {
6346
- if (observer) {
6347
- observer.disconnect();
6348
- observer = null;
6349
- }
6350
- };
6351
- })();
6352
- }, { selector: domSelector, callbackName: exposedFunctionName, cleanerName });
6328
+ }
6329
+ })();
6353
6330
  logger12.success("useCaptchaMonitor", `DOM \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${domSelector}`);
6354
6331
  cleanupFns.push(async () => {
6355
- try {
6356
- await page.evaluate((name) => {
6357
- if (window[name]) {
6358
- window[name]();
6359
- delete window[name];
6360
- }
6361
- }, cleanerName);
6362
- } catch {
6363
- }
6332
+ await domMonitorTask?.catch(() => {
6333
+ });
6364
6334
  });
6365
6335
  }
6366
6336
  if (urlPattern) {
@@ -6375,6 +6345,12 @@ function useCaptchaMonitor(page, options) {
6375
6345
  };
6376
6346
  page.on("framenavigated", frameHandler);
6377
6347
  logger12.success("useCaptchaMonitor", `URL \u76D1\u63A7\u5DF2\u542F\u7528\uFF1A${urlPattern}`);
6348
+ Promise.resolve().then(async () => {
6349
+ if (!isStopped && page.url().includes(urlPattern)) {
6350
+ await triggerDetected();
6351
+ }
6352
+ }).catch(() => {
6353
+ });
6378
6354
  cleanupFns.push(async () => {
6379
6355
  page.off("framenavigated", frameHandler);
6380
6356
  });
@@ -6382,10 +6358,10 @@ function useCaptchaMonitor(page, options) {
6382
6358
  return {
6383
6359
  stop: async () => {
6384
6360
  logger12.info("\u6B63\u5728\u505C\u6B62\u9A8C\u8BC1\u7801\u76D1\u63A7...");
6361
+ isStopped = true;
6385
6362
  for (const fn of cleanupFns) {
6386
6363
  await fn();
6387
6364
  }
6388
- isStopped = true;
6389
6365
  }
6390
6366
  };
6391
6367
  }
@@ -6430,7 +6406,7 @@ var Captcha = {
6430
6406
 
6431
6407
  // src/mutation.js
6432
6408
  import { createHash } from "node:crypto";
6433
- import { v4 as uuidv42 } from "uuid";
6409
+ import { v4 as uuidv4 } from "uuid";
6434
6410
  var logger13 = createInternalLogger("Mutation");
6435
6411
  var MUTATION_MONITOR_MODE = Object.freeze({
6436
6412
  Added: "added",
@@ -6438,7 +6414,7 @@ var MUTATION_MONITOR_MODE = Object.freeze({
6438
6414
  All: "all"
6439
6415
  });
6440
6416
  function generateKey(prefix) {
6441
- return `__${prefix}_${uuidv42().replace(/-/g, "_")}`;
6417
+ return `__${prefix}_${uuidv4().replace(/-/g, "_")}`;
6442
6418
  }
6443
6419
  var Mutation = {
6444
6420
  Mode: MUTATION_MONITOR_MODE,
@@ -6628,7 +6604,7 @@ var Mutation = {
6628
6604
  const overallTimeout = options.timeout ?? 180 * 1e3;
6629
6605
  const onMutation = options.onMutation;
6630
6606
  const pollInterval = 500;
6631
- const sleep = (ms) => new Promise((resolve) => {
6607
+ const sleep2 = (ms) => new Promise((resolve) => {
6632
6608
  setTimeout(resolve, ms);
6633
6609
  });
6634
6610
  const truncate = (value, max = 800) => {
@@ -6820,7 +6796,7 @@ var Mutation = {
6820
6796
  const deadline = Date.now() + overallTimeout;
6821
6797
  let lastState = state2;
6822
6798
  while (Date.now() < deadline) {
6823
- await sleep(pollInterval);
6799
+ await sleep2(pollInterval);
6824
6800
  lastState = await buildState();
6825
6801
  if (!lastState?.hasMatched) {
6826
6802
  continue;