Direct Javascript access in Puppeteer

Noam Rosenthal
Frontend Weekly
Published in
2 min readDec 27, 2017

I accidentally ran into this when I started using headless-chrome with the puppeteer project.

I love using puppeteer for testing browser code, and many times I use it to test Javascript libraries with a rich API.
But I got a bit bummed by the evaluate API. The environment inside the evaluate function and the connection with the environment outside of it feel too much disjointed and verbose, I have to pass too many parameters and remember their order.

For example, to use the scrollBy method, the following code needs to be written:

await page.evaluate((x, y) => window.scrollBy(x, y), x, y)

I have to repeat the parameters three times! This doesn’t feel right… I wanted the code to look more like:

await page.window.scrollBy(x, y)

So I played with ES6 proxies, trying to find the hack that would achieve this.
Doing that, I found an interesting feature of proxies when used with async/await code: the proxy trap would receive an “apply” call for the “then” function.

This was the bit I needed, and from there code similar to the above is actually possible! Also, you can now await regular getters inside the window, like this:

const window = directJSHandle(page.evaluate(() => window))
const tagName = await window.document.body.tagName

I use the proxy to chain and store all the getters, setters, and calls, and then break the chain when I receive the magic function call to “then”.

This is all available a small github project. It’s not yet ready to be maintained as an open source project (maybe it will if we start using it internally at Wix), but more like a concept.

Caveats: debugging code like this is a bit cumbersome and requires tools to ease the pain, and seeing “window” in a node context is confusing. But it was fun enough to share.

To be continued…

--

--

Noam Rosenthal
Frontend Weekly

Web Platform Architect. Improving browsers and specs. WebKit reviewer, Chromium contributor. Invited expert at Web Performance Group.