Why can't I access 'window' in an exposeFunction() function with Puppeteer?

不问归期 提交于 2019-12-03 14:28:38

evaluate the function

You can pass the dynamic script using evaluate.

(async function(){
    var puppeteer = require('puppeteer');
    const browser = await puppeteer.launch();
    const page = await browser.newPage();

    var functionToInject = function(){
        return window.navigator.appName;
    }

    var data = await page.evaluate(functionToInject); // <-- Just pass the function
    console.log(data); // outputs: Netscape

    await browser.close();
})()

addScriptTag and readFileSync

You can save the function to a seperate file and use the function using addScriptTag.

await page.addScriptTag({path: 'my-script.js'});

or evaluate with readFileSync.

await page.evaluate(fs.readFileSync(filePath, 'utf8'));

or, pass a parameterized funciton as a string to page.evaluate.

await page.evaluate(new Function('foo', 'console.log(foo);'), {foo: 'bar'});

Make a new function dynamicly

Do you need some other more way to deal with this? How about making it into a runnable function :D ?

function runnable(fn) {
  return new Function("arguments", `return ${fn.toString()}(arguments)`);
}

the above will create a new function with provided arguments. We can pass any function we want.

Such as the following function with window, along with arguments,

function functionToInject() {
  return window.location.href;
};

works flawlessly with promises too,

function functionToInject() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(window.location.href);
    }, 5000);
  });
}

and with arguments,

async function functionToInject(someargs) {
  return someargs; // {bar: 'foo'}
};

Call the desired function with evaluate,

var data = await page.evaluate(runnable(functionToInject), {bar: "foo"});
console.log(data); // shows the location

exposeFunction() isn't the right tool for this job.

From the Puppeteer docs

page.exposeFunction(name, puppeteerFunction)

puppeteerFunction Callback function which will be called in Puppeteer's context.

'In puppeteer's context' is a little vague, but check out the docs for evaluate():

page.evaluateHandle(pageFunction, ...args)

pageFunction Function to be evaluated in the page context

exposeFunction() doesn't expose a function to run inside the page, but exposes a function to be be run in node to be called from the page.

I have to use evaluate():

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!