rebrowser-playwright-core 1.64.1 → 1.64.100

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.
Files changed (2) hide show
  1. package/lib/coreBundle.js +113 -9
  2. package/package.json +1 -1
package/lib/coreBundle.js CHANGED
@@ -20586,6 +20586,24 @@ var init_utilityScriptSource = __esm({
20586
20586
  });
20587
20587
 
20588
20588
  // packages/playwright-core/src/server/javascript.ts
20589
+ function utilityScriptSource() {
20590
+ const source14 = source4;
20591
+ if (process.env["REBROWSER_PATCHES_SOURCE_URL"] === "0")
20592
+ return source14;
20593
+ if (!rebrowserUtilityScriptName) {
20594
+ const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
20595
+ const pick = () => letters[Math.floor(Math.random() * letters.length)];
20596
+ for (let i = 0; i < 1e3 && !rebrowserUtilityScriptName; i++) {
20597
+ const name2 = pick() + (Math.random() < 0.5 ? "" : pick());
20598
+ if (["do", "if", "in"].includes(name2) || new RegExp(`(^|[^\\w$.])${name2}(?![\\w$])`).test(source14))
20599
+ continue;
20600
+ rebrowserUtilityScriptName = name2;
20601
+ }
20602
+ }
20603
+ const name = rebrowserUtilityScriptName;
20604
+ const renamed = source14.replace("var UtilityScript = class {", () => `var ${name} = class {`).replace("UtilityScript: () => UtilityScript", () => `UtilityScript: () => ${name}`);
20605
+ return name && renamed.includes(`var ${name} = class {`) && renamed.includes(`UtilityScript: () => ${name}`) ? rebrowserUtilityScriptOffset + renamed : source14;
20606
+ }
20589
20607
  async function evaluate(context, returnByValue, pageFunction, ...args) {
20590
20608
  return evaluateExpression(context, String(pageFunction), { returnByValue, isFunction: typeof pageFunction === "function" }, ...args);
20591
20609
  }
@@ -20681,7 +20699,7 @@ function sparseArrayToString(entries) {
20681
20699
  }
20682
20700
  return "[" + tokens.join(", ") + "]";
20683
20701
  }
20684
- var ExecutionContext, JSHandle, JavaScriptErrorInEvaluate, snapshottedFunctionBuiltins, snapshottedObjectBuiltins, snapshottedTimerBuiltins, saveGlobalsSnapshotSource, mainWorldGlobalsSnapshotSource;
20702
+ var rebrowserUtilityScriptName, rebrowserUtilityScriptOffset, ExecutionContext, JSHandle, JavaScriptErrorInEvaluate, snapshottedFunctionBuiltins, snapshottedObjectBuiltins, snapshottedTimerBuiltins, saveGlobalsSnapshotSource, mainWorldGlobalsSnapshotSource;
20685
20703
  var init_javascript = __esm({
20686
20704
  "packages/playwright-core/src/server/javascript.ts"() {
20687
20705
  "use strict";
@@ -20690,6 +20708,7 @@ var init_javascript = __esm({
20690
20708
  init_debug();
20691
20709
  init_instrumentation();
20692
20710
  init_utilityScriptSource();
20711
+ rebrowserUtilityScriptOffset = "\n".repeat(Math.floor(Math.random() * 100));
20693
20712
  ExecutionContext = class extends SdkObject {
20694
20713
  constructor(parent, delegate, worldNameForTest, options) {
20695
20714
  super(parent, "execution-context");
@@ -20730,7 +20749,7 @@ var init_javascript = __esm({
20730
20749
  (() => {
20731
20750
  ${globalsSnapshot}
20732
20751
  const module = {};
20733
- ${source4}
20752
+ ${utilityScriptSource()}
20734
20753
  return new (module.exports.UtilityScript())(globalThis, ${isUnderTest()});
20735
20754
  })();`;
20736
20755
  this._utilityScriptPromise = this.raceAgainstContextDestroyed(this.delegate.rawEvaluateHandle(this, source14)).then((handle) => {
@@ -23407,6 +23426,27 @@ var init_screencast = __esm({
23407
23426
  });
23408
23427
 
23409
23428
  // packages/playwright-core/src/server/page.ts
23429
+ function bindingsControllerSource() {
23430
+ const source14 = source6;
23431
+ if (process.env["REBROWSER_PATCHES_RUNTIME_FIX_MODE"] === "0")
23432
+ return source14;
23433
+ const call = " this._global[this._globalBindingName](JSON.stringify(payload));\n";
23434
+ const retry2 = [
23435
+ " const json = JSON.stringify(payload);",
23436
+ " const send = (tries) => {",
23437
+ " const binding = this._global[this._globalBindingName];",
23438
+ ' if (typeof binding === "function")',
23439
+ " binding(json);",
23440
+ " else if (tries < 500)",
23441
+ " setTimeout(() => send(tries + 1), 10);",
23442
+ " else",
23443
+ ' data.callbacks.get(seq)?.reject(new Error(`binding "${bindingName}" is not available`));',
23444
+ " };",
23445
+ " send(0);",
23446
+ ""
23447
+ ].join("\n");
23448
+ return source14.split(call).length === 2 ? source14.replace(call, () => retry2) : source14;
23449
+ }
23410
23450
  async function ariaSnapshotJSONForFrame(progress2, frame, selector, options = {}) {
23411
23451
  const snapshot3 = await frame.retryWithProgressAndTimeouts(progress2, [1e3, 2e3, 4e3, 8e3], async (progress3, continuePolling) => {
23412
23452
  try {
@@ -24244,7 +24284,7 @@ var init_page = __esm({
24244
24284
  return new InitScript(browserContext, `
24245
24285
  (() => {
24246
24286
  const module = {};
24247
- ${source6}
24287
+ ${bindingsControllerSource()}
24248
24288
  const property = '${kBindingsControllerProperty}';
24249
24289
  if (!globalThis[property])
24250
24290
  globalThis[property] = new (module.exports.BindingsController())(globalThis, '${_PageBinding.kBindingName}');
@@ -24551,8 +24591,12 @@ var init_frames = __esm({
24551
24591
  } else {
24552
24592
  frame._currentDocument = { documentId, request: void 0 };
24553
24593
  }
24554
- if (process.env["REBROWSER_PATCHES_RUNTIME_FIX_MODE"] !== "0" && frame._rebrowserSession())
24594
+ if (process.env["REBROWSER_PATCHES_RUNTIME_FIX_MODE"] !== "0" && frame._rebrowserSession()) {
24555
24595
  frame._rebrowserDropContexts();
24596
+ if (this._page.browserContext.needsPlaywrightBinding())
24597
+ frame._rebrowserSession().send("Runtime.addBinding", { name: PageBinding.kBindingName }).catch(() => {
24598
+ });
24599
+ }
24556
24600
  frame._onClearLifecycle();
24557
24601
  const navigationEvent = { url: url3, name, newDocument: frame._currentDocument, isPublic: true };
24558
24602
  this._fireInternalFrameNavigation(frame, navigationEvent);
@@ -36336,7 +36380,7 @@ var init_chromiumSwitches = __esm({
36336
36380
  });
36337
36381
 
36338
36382
  // packages/playwright-core/src/server/chromium/crConnection.ts
36339
- var ConnectionEvents, kBrowserCloseMessageId, CRConnection, CRSession, CDPSession;
36383
+ var ConnectionEvents, kBrowserCloseMessageId, CRConnection, rebrowserLookupWorldName, rebrowserFallbackWarned, CRSession, CDPSession;
36340
36384
  var init_crConnection = __esm({
36341
36385
  "packages/playwright-core/src/server/chromium/crConnection.ts"() {
36342
36386
  "use strict";
@@ -36399,6 +36443,8 @@ var init_crConnection = __esm({
36399
36443
  return new CDPSession(this.rootSession, sessionId);
36400
36444
  }
36401
36445
  };
36446
+ rebrowserLookupWorldName = [...Array(Math.floor(Math.random() * (10 + 1)) + 10)].map(() => Math.random().toString(36)[2]).join("");
36447
+ rebrowserFallbackWarned = false;
36402
36448
  CRSession = class _CRSession extends SdkObject {
36403
36449
  constructor(connection, parentSession, sessionId, eventListener) {
36404
36450
  super(connection, "cr-session");
@@ -36507,7 +36553,45 @@ var init_crConnection = __esm({
36507
36553
  });
36508
36554
  }
36509
36555
  async __re__getMainWorld({ client, frameId, isWorker = false }) {
36556
+ try {
36557
+ const contextId4 = await this.__re__getMainWorldIdByObject({ client, frameId, isWorker });
36558
+ if (contextId4)
36559
+ return contextId4;
36560
+ } catch (error) {
36561
+ process.env["REBROWSER_PATCHES_DEBUG"] && console.log("[rebrowser-patches][getMainWorld] object lookup failed, using a binding:", error);
36562
+ }
36563
+ if (!rebrowserFallbackWarned) {
36564
+ rebrowserFallbackWarned = true;
36565
+ console.warn("[rebrowser-patches] could not look up the page's context id without touching the page; falling back to a binding handshake that page scripts can notice. Please report this with your Chrome version. REBROWSER_PATCHES_RUNTIME_FIX_MODE=alwaysIsolated avoids it.");
36566
+ }
36567
+ return this.__re__getMainWorldByBinding({ client, frameId, isWorker });
36568
+ }
36569
+ // A worker evaluates `this` in its only context. A frame reads `document` in an isolated world and resolves that
36570
+ // node again without a context, which lands in the frame's main world. Either way the remote object id is
36571
+ // "<isolate>.<contextId>.<id>".
36572
+ async __re__getMainWorldIdByObject({ client, frameId, isWorker }) {
36573
+ const objectGroup = "g" + Math.random().toString(36).slice(2);
36574
+ let objectId;
36575
+ try {
36576
+ if (isWorker) {
36577
+ objectId = (await client.send("Runtime.evaluate", { expression: "this", objectGroup })).result.objectId;
36578
+ } else {
36579
+ const { executionContextId } = await client.send("Page.createIsolatedWorld", { frameId, worldName: rebrowserLookupWorldName, grantUniveralAccess: true });
36580
+ const { result: result2 } = await client.send("Runtime.evaluate", { expression: "document", contextId: executionContextId, objectGroup });
36581
+ const { node } = await client.send("DOM.describeNode", { objectId: result2.objectId });
36582
+ objectId = (await client.send("DOM.resolveNode", { backendNodeId: node.backendNodeId, objectGroup })).object.objectId;
36583
+ }
36584
+ } finally {
36585
+ client.send("Runtime.releaseObjectGroup", { objectGroup }).catch(() => {
36586
+ });
36587
+ }
36588
+ const match = /^-?\d+\.(\d+)\.\d+$/.exec(objectId || "");
36589
+ process.env["REBROWSER_PATCHES_DEBUG"] && console.log(`[rebrowser-patches][getMainWorldIdByObject] frameId = ${frameId}, objectId = ${objectId}`);
36590
+ return match ? Number(match[1]) : void 0;
36591
+ }
36592
+ async __re__getMainWorldByBinding({ client, frameId, isWorker = false }) {
36510
36593
  let contextId4;
36594
+ let identifier;
36511
36595
  const randomName = [...Array(Math.floor(Math.random() * (10 + 1)) + 10)].map(() => Math.random().toString(36)[2]).join("");
36512
36596
  process.env["REBROWSER_PATCHES_DEBUG"] && console.log(`[rebrowser-patches][getMainWorld] binding name = ${randomName}`);
36513
36597
  await client.send("Runtime.addBinding", {
@@ -36537,10 +36621,11 @@ var init_crConnection = __esm({
36537
36621
  expression: `this['${randomName}']('${frameId}')`
36538
36622
  });
36539
36623
  } else {
36540
- await client.send("Page.addScriptToEvaluateOnNewDocument", {
36541
- source: `document.addEventListener('${randomName}', (e) => self['${randomName}'](e.detail.frameId))`,
36624
+ ({ identifier } = await client.send("Page.addScriptToEvaluateOnNewDocument", {
36625
+ // use `window`, not `self`: pages can reassign `self` (or make it throw, e.g. LavaMoat scuttling), `window` is unforgeable
36626
+ source: `document.addEventListener('${randomName}', (e) => window['${randomName}'](e.detail.frameId))`,
36542
36627
  runImmediately: true
36543
- });
36628
+ }));
36544
36629
  const createIsolatedWorldResult = await client.send("Page.createIsolatedWorld", {
36545
36630
  frameId,
36546
36631
  // use randomName for worldName to distinguish from normal utility world
@@ -36553,6 +36638,14 @@ var init_crConnection = __esm({
36553
36638
  });
36554
36639
  }
36555
36640
  process.env["REBROWSER_PATCHES_DEBUG"] && console.log(`[rebrowser-patches][getMainWorld] result:`, { contextId: contextId4 });
36641
+ client.send("Runtime.removeBinding", { name: randomName }).catch(() => {
36642
+ });
36643
+ if (contextId4)
36644
+ client.send("Runtime.evaluate", { expression: `delete this['${randomName}']`, contextId: contextId4 }).catch(() => {
36645
+ });
36646
+ if (identifier)
36647
+ client.send("Page.removeScriptToEvaluateOnNewDocument", { identifier }).catch(() => {
36648
+ });
36556
36649
  return contextId4;
36557
36650
  }
36558
36651
  async __re__getIsolatedWorld({ client, frameId, worldName }) {
@@ -39450,7 +39543,18 @@ var init_crPage = __esm({
39450
39543
  async _onBindingCalled(event) {
39451
39544
  const pageOrError = await this._crPage._page.waitForInitializedOrError();
39452
39545
  if (!(pageOrError instanceof Error)) {
39453
- const context = this._contextIdToContext.get(event.executionContextId);
39546
+ let context = this._contextIdToContext.get(event.executionContextId);
39547
+ if (!context && process.env["REBROWSER_PATCHES_RUNTIME_FIX_MODE"] !== "0" && event.payload.startsWith("{")) {
39548
+ for (const frame of this._page.frameManager.frames()) {
39549
+ if (frame._rebrowserSession() !== this._client)
39550
+ continue;
39551
+ await frame.context("main").catch(() => {
39552
+ });
39553
+ context = this._contextIdToContext.get(event.executionContextId);
39554
+ if (context)
39555
+ break;
39556
+ }
39557
+ }
39454
39558
  if (context)
39455
39559
  await this._page.onBindingCalled(event.payload, context);
39456
39560
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rebrowser-playwright-core",
3
- "version": "1.64.1",
3
+ "version": "1.64.100",
4
4
  "description": "A drop-in replacement for playwright-core patched with rebrowser-patches. It allows to pass modern automation detection tests.",
5
5
  "keywords": [
6
6
  "rebrowser",