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

[Feature] Expose JSHandle _remoteObject #2275

Closed
nojvek opened this issue May 17, 2020 · 4 comments
Closed

[Feature] Expose JSHandle _remoteObject #2275

nojvek opened this issue May 17, 2020 · 4 comments
Assignees

Comments

@nojvek
Copy link

nojvek commented May 17, 2020

When I debug the the console messages passed via

        page.on(`console`, (msg) => {
          const msgType = msg.type();
          const args = msg.args()
          // proxy browser console stream
          console[msgType](args);

All I see is a bunch of JSHandles, I tried to figure out if I can get a usable value out of it, like strings, numbers, or proper Error objects with intact stack traces, but I couldn't

I just want to proxy the console error messages from browser to node process

how do I do this ?

EDIT:

await the jsonValue() helps but I still don't get errors

      await new Promise((resolve, reject) => {
        // lint rule is very aggresive,
        // eslint-disable-next-line @typescript-eslint/no-misused-promises
        page.on(`console`, async (msg) => {
          const msgType = msg.type();
          const args = await Promise.all(msg.args().map((jsHandle) => jsHandle.jsonValue()));
          // proxy browser console stream
          // eslint-disable-next-line no-console
          console[msgType](...args);
        });
      });

Do you have plans to expose _remoteObject ? Seems like we could write a simple function that could return JS like objects for errors types.

@pavelfeldman
Copy link
Member

pavelfeldman commented May 17, 2020

The simplest way to proxy is:

page.on('console', console.log);

If you'd like to process arguments, you can use arg.jsonValue() and arg.getProperties(). Underlying remote object does give you more details...

@nojvek
Copy link
Author

nojvek commented May 17, 2020

I did try arg.jsonValue() but it gave {} for errors.

If anyone else hits this same problem, this is something that sort of works.

        let msgType = msg.type();
        msgType = msgType === `warning` ? `warn` : msgType; // so we can feed it to console.warn
        const msgText = msg.text();
        const args = msg.args().map((jsHandle) => {
          // see https://github.com/microsoft/playwright/issues/2275
          const remoteObject = jsHandle[`_remoteObject`];
          if (Object.prototype.hasOwnProperty.call(remoteObject, `value`)) {
            return remoteObject.value;
          } else if (remoteObject.type === `object` && remoteObject.subtype === `error` && remoteObject.description) {
            const errStack = remoteObject.description;
            const errMessage = errStack.split(`\n`)[0];
            const err = new Error(errMessage);
            err.stack = errStack;
            return err;
          }
          // we don't know how to parse this out yet, return as is
          return remoteObject;
        });

        // proxy browser console stream
        console[msgType](...args);

It turns out, getting error messages out of console in a uniform way from firefox, chromium, webkit is quite tricky.

I'll bash my head more against this to dig even deeper but ideal experience I'm looking for is rich console proxying.

@pavelfeldman , just want to say, I'm very grateful for your contributions to chrome-devtools -> puppeteer -> playwright. Thanks for building amazing things. Really loving playwright.

@pavelfeldman
Copy link
Member

pavelfeldman commented May 17, 2020

Hang on, trying to understand your scenario. We definitely don't want it to be that complicated to process errors. Is it something like below?

console.log(new Error("error message"));

If that is the case, we definitely want to make jsonValue work for you and return an object with error message and stack in case of errors. Before we do that, you can do the following:

const {message, stack} = await arg.evaluate(error => ({
    message: error.message,
    stack: error.stack
}));

What happens above is we take a handle to an error message and evaluate on it, cherry picking two property values that we return as values, not as a handle.

@pavelfeldman
Copy link
Member

Closing as fixed in #2329

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

No branches or pull requests

2 participants