Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

debug in chromium / puppeteer doesn't populate evaluate script

So I have the following code launching

this.browser = await puppeteer.launch( { headless: false, devtools: true, slowMo: 200});
this.page = await this.browser.newPage();

await this.page.goto(pageUrl);

let result = await this.page.evaluate(() => {
            const labels = document.querySelectorAll("li.product-item");

            let productList = [];

            for(let product of labels) {
                productList.push(product);
            }
            debugger;

            //filter only product stacks that have a price
            const productStacks = productList.filter(product => product.querySelector("span.price-wrapper") !== null);

            let results = productStacks.map(product => {
                return product.querySelector("span.price-wrapper").getAttribute("data-price-amount");
            });

            return results;
        });

So chromium starts up and pauses at the appropriate code (as best as I can tell), I can even see the local variables populate with the expect result and step through the code, however the open file puppeteer_evaluation_script is not populated with the evaluation script and remains with the contents, so I'm stepping through blind.

//# sourceURL=__puppeteer_evaluation_script__

Occasionally after many minutes it sometimes does actually populate with the code. I have no idea what's wrong, I've tried updating the latest node lts and puppeteer but have the same behavior.

like image 803
Pork 'n' Bunny Avatar asked Nov 07 '22 03:11

Pork 'n' Bunny


1 Answers

I don't know what causes this issue, but here is a pair of possible solutions.

To avoid getting:

//# sourceURL=__puppeteer_evaluation_script__

You can expose a function:

const puppeteer = require('puppeteer'); 

var browser = null;
var page = null;

(async () => 
{
    browser = await puppeteer.launch(
    {
        headless: false,
        devtools: true,
    });

    page = await browser.newPage();

    await page.goto("https://google.com/");

    // Expose a function
    page.exposeFunction("nothing", () => null);


    await page.evaluate(async function()
    {
        debugger;
        
        console.log("Do task");
    });
})();

In case that fails in the future. I made a wrapper for using eval() since the source appears using that. It works with both sync and async functions and supports passing args and returning values.

function evaluateFixed(page, realFunction)
{
    return page.evaluate(async function(realFunction, args)
    {
        var func = eval(`(${realFunction})`);

        if(func.constructor.name === "AsyncFunction")
            return await func(...args);
        else
            return func(...args);
    },
    realFunction.toString(), Array.from(arguments).slice(2));
}


(async () => 
{
    browser = await puppeteer.launch(
    {
        headless: false,
        devtools: true,
    });

    
    page = await browser.newPage();

    await page.goto("https://google.com/");

    console.log("Doing test");

    let res = await evaluateFixed(page, async function(x, y, z)
    {
        debugger;

        console.log("Do task", x, y, z);

        function sleep(amount)
        {
            return new Promise((resolve) => setTimeout(resolve, amount));
        }
        
        for(let  i = 0; i < 10; i++)
        {
            console.log("on seconds", i);
            await sleep(1000);
        }

        return { "fee": "foo" };

    }, 1, "two", { "three": 3});
    
    console.log("Res 1", res);
    

    res = await evaluateFixed(page, () =>
    {
        debugger;

        return 1 + 2;
    });
    
    console.log("Res 2", res);
    
})();
like image 178
John Avatar answered Nov 11 '22 02:11

John