puppeteer-extra icon indicating copy to clipboard operation
puppeteer-extra copied to clipboard

[Bug] `RangeError: Maximum call stack size exceeded` because of hacks to `Function.prototype.toString` in `puppeteer-extra-plugin-stealth`

Open nomagick opened this issue 1 year ago • 6 comments

Describe the bug With puppeteer-extra-plugin-stealth plugin applied, open any page in the internet archive, for example https://web.archive.org/web/20240513040624/https://www.google.com/ Then go to the terminal, you will see RangeError: Maximum call stack size exceeded triggered for .toString() calls to any function.

I've looked into the code a bit and found the plugin making a lot of hacks to Function.prototype in some util function and the util function is used in many other places.

It might be the way-back-machine also hacking the browser environment a bit and some how it created a loop.

TBH I didn't quite get the purpose of the hacking and why it's always applied globally to Function.prototype.

But it might be time to consider refactoring this hack to use some constant WeakMap instead of chaining functions.

Code Snippet

const puppeteer = require('puppeteer-extra')
const StealthPlugin = require('puppeteer-extra-plugin-stealth')
puppeteer.use(StealthPlugin())

;(async () => {
  const browser = await puppeteer.launch({headless: false})
  const page = await browser.newPage()
  await page.goto('https://web.archive.org/web/20240513040624/https://www.google.com/')
  // ...
})()

nomagick avatar May 13 '24 06:05 nomagick

I'm having the same issue in this page: https://www.liverpool.com.mx/tienda/pdp/honor-x6a-plus-lcd-6.7-pulgadas-desbloqueado/1156981440?skuid=1156981440 Seems like tricks in the function prototype are creating weird issues, I was able to pin down the issue to a call inside lodash:

/** Used to detect if a method is native. */
var reIsNative = RegExp('^' +
  funcToString$1.call(hasOwnProperty$1).replace(reRegExpChar, '\\$&')
  .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);

image

Ivanca avatar Jul 07 '24 09:07 Ivanca

This is because they change toString in their own script.

vladtreny avatar Jul 07 '24 11:07 vladtreny

A very temporary solution

            await page.evaluateOnNewDocument(() => {
                delete Function.prototype.toString
            })

vladtreny avatar Jul 07 '24 11:07 vladtreny

This very temporary solution worked for me @vladtreny :) ... wondering if you or other folks managed to implement a definitive solution for that ...

oiluis avatar Dec 30 '24 03:12 oiluis

@vladtreny Thanks for the temp solution idea - it worked for us in some cases but not others. Did you ever find a more permanent solution?

Ollie1700 avatar Mar 12 '25 15:03 Ollie1700

send code to reproduce where it does not work

vladtreny avatar Mar 12 '25 15:03 vladtreny