Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

evaluate - strange execute sequence #324

Closed
atian25 opened this issue Aug 17, 2017 · 12 comments
Closed

evaluate - strange execute sequence #324

atian25 opened this issue Aug 17, 2017 · 12 comments
Labels

Comments

@atian25
Copy link

atian25 commented Aug 17, 2017

scripts:

const puppeteer = require('puppeteer');
(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  page.on('console', console.log);
  await page.goto('https://google.com');
  await page.evaluate(async () => {
    console.log('1. abc');
    console.log('2. ', this);
    console.log('3. ', this.document.title);
    console.log('4. ', this.window);
  });
  browser.close();
})();

output:

➜  headless node index.js
1. abc
3.  Google
2.  Window
4.  Window
@pavelfeldman
Copy link
Contributor

Nice one, thanks for reporting it.

@aslushnikov: this sounds like an argument towards support for objectHandles.

@JoelEinbinder
Copy link
Collaborator

@pavelfeldman ok I am stumped. What does this have to do with object handles?

@aslushnikov
Copy link
Contributor

Joel: they would save us some round trips

@JoelEinbinder
Copy link
Collaborator

Ooooh

@pavelfeldman
Copy link
Contributor

@JoelEinbinder: it is essential that we emit events (not only console ones) in order. That way for the user script

console.log(window);
document.body.offsetWidth;
console.log(document);

we would get LOG, LAYOUT, LOG notifications in order.

That means that you need to emit LOG ones immediately and the arguments of those events become lazily evaluated. Which is objectHandles. Not necessarily generically exposed via API at this point, but why exposing in an ad-hoc manner if we already need to deal with dispose :/

@pavelfeldman
Copy link
Contributor

... or we introduce Runtime.enable({consoleMagic}) which is serializing console parameters on the backend side. Basically what @aslushnikov is doing on the client side moves to the server. Which in turn makes elementHandles tough to encode... Or we do both 😄

@JoelEinbinder
Copy link
Collaborator

I was thinking we just make the values from console.log be promises.

@pavelfeldman
Copy link
Contributor

This can be fixed once #382 is done.

aslushnikov added a commit to aslushnikov/puppeteer that referenced this issue Oct 6, 2017
This patch starts dispatching JSHandle instances as console arguments.

BREAKING CHANGE: this changes the API of the ConsoleMessage.

Fixes puppeteer#324.
aslushnikov added a commit that referenced this issue Oct 10, 2017
This patch starts dispatching JSHandle instances as console arguments.

BREAKING CHANGE: this changes the API of the ConsoleMessage.

Fixes #324.
@thomas-darling
Copy link

thomas-darling commented Nov 1, 2017

Soo, how are we supposed to get the console log messages now?

According to https://github.com/GoogleChrome/puppeteerstill, this should work - but it doesn't.
page.on('console', msg => console.log('PAGE LOG:', ...msg.args));

Edit:
Ok, it actually does work - but it's not very readable.
Also, let's say I wanted the console messages as an array of arrays, where the inner arrays represent the args passed to each console.log call. How would I get that from those JSHandle's?

@aslushnikov
Copy link
Contributor

@thomas-darling I'm not sure I follow. Is the question "how do I use JSHandle"?

@thomas-darling
Copy link

Yeah, sorry for the less than clear question.

Based on the documentation on the page I mentioned, I expected that line of code to forward the console log calls with the original arguments - but what I got in my console was a bunch of stringified JSHandles, which at first didn't seem to include the actual log messages - although on closer inspection, I realized they were in fact in there.

What I was trying to achieve, was to simply get the original arguments for the console.log calls made by the page. Given that those arguments are now JSHandles, I'm not quite sure how to best get the actual argument values from those handles?

@aslushnikov
Copy link
Contributor

@thomas-darling ah I see. For logging, JSHandle's jsonValue would work just fine.

page.on('console', async msg => {
  const jsonArgs = await Promise.all(msg.args.map(arg => arg.jsonValue()));
  console.log('PAGE LOG:', ...jsonArgs);
});

Note: this might shuffle the log messages between each other because you await inside the function.

If you need the order retained, you can retain it manually:

let chain = Promise.resolve();
page.on('console', msg => {
  chain = chain.then(async function() {
    const jsonArgs = await Promise.all(msg.args.map(arg => arg.jsonValue()));
    console.log('PAGE LOG:', ...jsonArgs);
  });
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants