xvrh / puppeteer-dart

A Dart library to automate the Chrome browser over the DevTools Protocol. This is a port of the Puppeteer API
BSD 3-Clause "New" or "Revised" License
225 stars 56 forks source link

evaluate returns null when expected result is a list #243

Open rohitsangwan01 opened 1 year ago

rohitsangwan01 commented 1 year ago

Hey thanks for this awesome library

am facing an issue when i try to evaluate a method which should return a list, then evaluate method returns null but if i use evaluateHandle, then it returns list of JsHandle which seems to be fine

and i am sure that , js method is fine and returns proper value, because i tried executing that manually and its fine and am facing this issue only when expecting result is a List, rest all cases works fine

with this , i also face an issue if i try to execute a method with parameter as list, for example

evaluate('''SomeMethod( [ "someData" ] )''') this will not work

but this works : evaluate('''SomeMethod( [ ] )'''), or we pass something else , that will also works and i have to pass args like this , can't use args parameter from Puppeteer in my case

xvrh commented 1 year ago

Can you provide a way to reproduce?

Just tried something like that and it seems to work as expected:

import 'package:puppeteer/puppeteer.dart';

void main() async {
  var browser = await puppeteer.launch();
  var page = await browser.newPage();

  var result = await page.evaluate('() => ["someData"]');
  print('$result ${(result as List).first} ${result.runtimeType}');
  // => [someData] someData List<dynamic>

  var result2 = await page.evaluate('(a) => a', args: [
    ['myarg']
  ]);
  print('$result2 ${(result2 as List).first} ${result2.runtimeType}');
  // => [myarg] myarg List<dynamic>

  await browser.close();
}
rohitsangwan01 commented 1 year ago

@xvrh here in my library am using puppeteer for desktop and when i call this method or other similar methods which should return a list, but returning null

but on mobile platform it returns correct list

for desktop am using this to get result, and if i use evaluateHandler instead of this , then am getting a list (but in JsHandler form )

on mobile am using this

Edit : and are you able to evaluate a method with args as list, for example in my case page?.evaluate('''Wpp.someMethod("arg1",["arg2","arg3"]);''') so here if i pass list as argument within the method string, then puppeteer throws some error i can't use this page.evaluate('(a) => a', args: [['myarg']]); because i have to build a string common for both mobile and desktop platform

xvrh commented 1 year ago

In your evaluateJs implementation in wp_client_desktop, can you wrap the source inside a function?

var result = await page?.evaluate('() => $source');
rohitsangwan01 commented 1 year ago

In your evaluateJs implementation in wp_client_desktop, can you wrap the source inside a function?

var result = await page?.evaluate('() => $source');

yes trying

rohitsangwan01 commented 1 year ago

@xvrh adding '() => $source' have same result , fixed that list issue ( passing list as args )

but still getting issue in getting result when expecting list Here is result of

evaluate : null evaluateHandle -> properties : {0: JSHandle@object, 1: JSHandle@object, 2: JSHandle@object, 3: JSHandle@object}

rohitsangwan01 commented 1 year ago

@xvrh tried to replicating something like this

  String content = '''
        window.getData = () => {
          return new Promise((resolve, reject) => {
            setTimeout(() => {
              resolve([{ "someData" : 3 },{ "randomData" : 2}])
            }, 1000);
          });
        };
    ''';

  await page.addScriptTag(content: content, type: "module");
  var result = await page.evaluate('window.getData()');

and its also working fine, but strangely its not working as expected in my library when i use WPP.group.getAllGroups(); but if i execute this on mobile ( in webView ), then returning result do you think this can be because of large data or large list or something unable to parse in json ?

rohitsangwan01 commented 1 year ago

@xvrh one thing i noticed with these methods which are returning null is : evaluateHandle returns jsHandler but jsHandler.jsonValue throws error : Object reference chain is too long and jsHandler.jsonValue works fine for other methods ( which are already working fine with evaluate )

xvrh commented 1 year ago

do you think this can be because of large data or large list or something unable to parse in json

Can you try to debug by taking only some small part of the array. ie:

  var result = await page.evaluate('async () => (await WPP.group.getAllGroups()).slice(0, 10)');
rohitsangwan01 commented 1 year ago

still getting null after trying async () => (await WPP.group.getAllGroups()).slice(0, 10)'

i also tried : async () => (await WPP.group.getAllGroups())[0] and got null

but when i tried evaluateHandle with above , i got the result as expected ( in jsHandle ) jsHandle.properties returns : {revisionNumber: JSHandle:32, __x_stale: JSHandle@object, __fired: JSHandle:null, ........

rohitsangwan01 commented 1 year ago

@xvrh finally got the solution

This worked for me : var result = await page?.evaluate('async () => JSON.stringify(await WPP.group.getAllGroups())');

seems like issue is with the parsing on dart side, if we parse the result within js , then its working fine