{"action":"created","comment":{"url":"https://api.github.com/repos/scrapinghub/splash/pulls/comments/23787534","id":23787534,"diff_hunk":"@@ -503,6 +511,64 @@ def runjs(self, js_source, handle_errors=True):\n         js_source = \"%s;undefined\" % js_source\n         self.evaljs(js_source, handle_errors=handle_errors)\n \n+    def wait_for_resume(self, js_source, callback, errback, timeout):\n+        \"\"\"\n+        Run some Javascript asynchronously.\n+\n+        The JavaScript must contain a method called `main()` that accepts\n+        one argument. The first argument will be an object with `resume()`\n+        and `error()` methods. The code _must_ call one of these functions\n+        before the timeout or else it will be canceled.\n+\n+        Note: this cleans up the JavaScript global variable that it creates,\n+        but QT seems to notice when a JS GV is deleted and it destroys the\n+        underlying C++ object. Therefore, we can only delete the JS GV _after_\n+        the user's code has called us back. This should change in QT5, since\n+        it will then be possible to specify a different object ownership\n+        policy when calling addToJavaScriptWindowObject().\n+        \"\"\"\n+\n+        frame = self.web_page.mainFrame()\n+        script_text = js_source.replace('\\n', ' \\\\\\n').replace('\\\"', '\\\\\"')\n+        callback_proxy = OneShotCallbackProxy(self, callback, errback, timeout)\n+        frame.addToJavaScriptWindowObject(callback_proxy.name, callback_proxy)\n+\n+        wrapped = \"\"\"\n+        (function () {\n+            try {\n+                eval(\"%(script_text)s\");\n+            } catch (err) {\n+                var main = function (splash) {\n+                    splash.error(err);","path":"splash/browser_tab.py","position":60,"original_position":60,"commit_id":"99f28f4b59c36e5f6727414b6865de9ba717fdba","original_commit_id":"99f28f4b59c36e5f6727414b6865de9ba717fdba","user":{"login":"mehaase","id":320904,"avatar_url":"https://avatars.githubusercontent.com/u/320904?v=3","gravatar_id":"","url":"https://api.github.com/users/mehaase","html_url":"https://github.com/mehaase","followers_url":"https://api.github.com/users/mehaase/followers","following_url":"https://api.github.com/users/mehaase/following{/other_user}","gists_url":"https://api.github.com/users/mehaase/gists{/gist_id}","starred_url":"https://api.github.com/users/mehaase/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mehaase/subscriptions","organizations_url":"https://api.github.com/users/mehaase/orgs","repos_url":"https://api.github.com/users/mehaase/repos","events_url":"https://api.github.com/users/mehaase/events{/privacy}","received_events_url":"https://api.github.com/users/mehaase/received_events","type":"User","site_admin":false},"body":"This is related to your 'why stringified' question. QT slots like `resume()` and `error()` must declare the types of their arguments, and those two currently declare 1 `str` argument. Therefore, QT will stringify whatever is passed to `resume()` or `error()`. That's why `toString()` is necessary in other places, perhaps, but not here. I'll take another look at it just to confirm.\r\n\r\nI'm going to see if QT will let me overload `resume()` so that it could accept different types of arguments. If I can do that, then I can convert those arguments to the proper Lua types.","created_at":"2015-01-29T17:56:38Z","updated_at":"2015-01-29T17:56:38Z","html_url":"https://github.com/scrapinghub/splash/pull/162#discussion_r23787534","pull_request_url":"https://api.github.com/repos/scrapinghub/splash/pulls/162","_links":{"self":{"href":"https://api.github.com/repos/scrapinghub/splash/pulls/comments/23787534"},"html":{"href":"https://github.com/scrapinghub/splash/pull/162#discussion_r23787534"},"pull_request":{"href":"https://api.github.com/repos/scrapinghub/splash/pulls/162"}}},"pull_request":{"url":"https://api.github.com/repos/scrapinghub/splash/pulls/162","id":27778107,"html_url":"https://github.com/scrapinghub/splash/pull/162","diff_url":"https://github.com/scrapinghub/splash/pull/162.diff","patch_url":"https://github.com/scrapinghub/splash/pull/162.patch","issue_url":"https://api.github.com/repos/scrapinghub/splash/issues/162","number":162,"state":"open","locked":false,"title":"Allow JavaScript callback to resume Lua coroutine","user":{"login":"mehaase","id":320904,"avatar_url":"https://avatars.githubusercontent.com/u/320904?v=3","gravatar_id":"","url":"https://api.github.com/users/mehaase","html_url":"https://github.com/mehaase","followers_url":"https://api.github.com/users/mehaase/followers","following_url":"https://api.github.com/users/mehaase/following{/other_user}","gists_url":"https://api.github.com/users/mehaase/gists{/gist_id}","starred_url":"https://api.github.com/users/mehaase/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mehaase/subscriptions","organizations_url":"https://api.github.com/users/mehaase/orgs","repos_url":"https://api.github.com/users/mehaase/repos","events_url":"https://api.github.com/users/mehaase/events{/privacy}","received_events_url":"https://api.github.com/users/mehaase/received_events","type":"User","site_admin":false},"body":"As we discussed here: https://github.com/scrapinghub/splash/issues/122","created_at":"2015-01-21T17:26:19Z","updated_at":"2015-01-29T17:56:38Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1b44dc0579015ba24c88c1a25e46f8518d53c62b","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/scrapinghub/splash/pulls/162/commits","review_comments_url":"https://api.github.com/repos/scrapinghub/splash/pulls/162/comments","review_comment_url":"https://api.github.com/repos/scrapinghub/splash/pulls/comments/{number}","comments_url":"https://api.github.com/repos/scrapinghub/splash/issues/162/comments","statuses_url":"https://api.github.com/repos/scrapinghub/splash/statuses/99f28f4b59c36e5f6727414b6865de9ba717fdba","head":{"label":"mehaase:js_yield_to_lua","ref":"js_yield_to_lua","sha":"99f28f4b59c36e5f6727414b6865de9ba717fdba","user":{"login":"mehaase","id":320904,"avatar_url":"https://avatars.githubusercontent.com/u/320904?v=3","gravatar_id":"","url":"https://api.github.com/users/mehaase","html_url":"https://github.com/mehaase","followers_url":"https://api.github.com/users/mehaase/followers","following_url":"https://api.github.com/users/mehaase/following{/other_user}","gists_url":"https://api.github.com/users/mehaase/gists{/gist_id}","starred_url":"https://api.github.com/users/mehaase/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mehaase/subscriptions","organizations_url":"https://api.github.com/users/mehaase/orgs","repos_url":"https://api.github.com/users/mehaase/repos","events_url":"https://api.github.com/users/mehaase/events{/privacy}","received_events_url":"https://api.github.com/users/mehaase/received_events","type":"User","site_admin":false},"repo":{"id":28943896,"name":"splash","full_name":"mehaase/splash","owner":{"login":"mehaase","id":320904,"avatar_url":"https://avatars.githubusercontent.com/u/320904?v=3","gravatar_id":"","url":"https://api.github.com/users/mehaase","html_url":"https://github.com/mehaase","followers_url":"https://api.github.com/users/mehaase/followers","following_url":"https://api.github.com/users/mehaase/following{/other_user}","gists_url":"https://api.github.com/users/mehaase/gists{/gist_id}","starred_url":"https://api.github.com/users/mehaase/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mehaase/subscriptions","organizations_url":"https://api.github.com/users/mehaase/orgs","repos_url":"https://api.github.com/users/mehaase/repos","events_url":"https://api.github.com/users/mehaase/events{/privacy}","received_events_url":"https://api.github.com/users/mehaase/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mehaase/splash","description":"Lightweight, scriptable browser as a service with an HTTP API","fork":true,"url":"https://api.github.com/repos/mehaase/splash","forks_url":"https://api.github.com/repos/mehaase/splash/forks","keys_url":"https://api.github.com/repos/mehaase/splash/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mehaase/splash/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mehaase/splash/teams","hooks_url":"https://api.github.com/repos/mehaase/splash/hooks","issue_events_url":"https://api.github.com/repos/mehaase/splash/issues/events{/number}","events_url":"https://api.github.com/repos/mehaase/splash/events","assignees_url":"https://api.github.com/repos/mehaase/splash/assignees{/user}","branches_url":"https://api.github.com/repos/mehaase/splash/branches{/branch}","tags_url":"https://api.github.com/repos/mehaase/splash/tags","blobs_url":"https://api.github.com/repos/mehaase/splash/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mehaase/splash/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mehaase/splash/git/refs{/sha}","trees_url":"https://api.github.com/repos/mehaase/splash/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mehaase/splash/statuses/{sha}","languages_url":"https://api.github.com/repos/mehaase/splash/languages","stargazers_url":"https://api.github.com/repos/mehaase/splash/stargazers","contributors_url":"https://api.github.com/repos/mehaase/splash/contributors","subscribers_url":"https://api.github.com/repos/mehaase/splash/subscribers","subscription_url":"https://api.github.com/repos/mehaase/splash/subscription","commits_url":"https://api.github.com/repos/mehaase/splash/commits{/sha}","git_commits_url":"https://api.github.com/repos/mehaase/splash/git/commits{/sha}","comments_url":"https://api.github.com/repos/mehaase/splash/comments{/number}","issue_comment_url":"https://api.github.com/repos/mehaase/splash/issues/comments/{number}","contents_url":"https://api.github.com/repos/mehaase/splash/contents/{+path}","compare_url":"https://api.github.com/repos/mehaase/splash/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mehaase/splash/merges","archive_url":"https://api.github.com/repos/mehaase/splash/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mehaase/splash/downloads","issues_url":"https://api.github.com/repos/mehaase/splash/issues{/number}","pulls_url":"https://api.github.com/repos/mehaase/splash/pulls{/number}","milestones_url":"https://api.github.com/repos/mehaase/splash/milestones{/number}","notifications_url":"https://api.github.com/repos/mehaase/splash/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mehaase/splash/labels{/name}","releases_url":"https://api.github.com/repos/mehaase/splash/releases{/id}","created_at":"2015-01-08T02:00:26Z","updated_at":"2015-01-20T16:46:59Z","pushed_at":"2015-01-29T05:53:21Z","git_url":"git://github.com/mehaase/splash.git","ssh_url":"git@github.com:mehaase/splash.git","clone_url":"https://github.com/mehaase/splash.git","svn_url":"https://github.com/mehaase/splash","homepage":"","size":1114,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"scrapinghub:master","ref":"master","sha":"110b005b4e693c3ddedf31288fe3c3b4f32d5c70","user":{"login":"scrapinghub","id":699596,"avatar_url":"https://avatars.githubusercontent.com/u/699596?v=3","gravatar_id":"","url":"https://api.github.com/users/scrapinghub","html_url":"https://github.com/scrapinghub","followers_url":"https://api.github.com/users/scrapinghub/followers","following_url":"https://api.github.com/users/scrapinghub/following{/other_user}","gists_url":"https://api.github.com/users/scrapinghub/gists{/gist_id}","starred_url":"https://api.github.com/users/scrapinghub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scrapinghub/subscriptions","organizations_url":"https://api.github.com/users/scrapinghub/orgs","repos_url":"https://api.github.com/users/scrapinghub/repos","events_url":"https://api.github.com/users/scrapinghub/events{/privacy}","received_events_url":"https://api.github.com/users/scrapinghub/received_events","type":"Organization","site_admin":false},"repo":{"id":10182205,"name":"splash","full_name":"scrapinghub/splash","owner":{"login":"scrapinghub","id":699596,"avatar_url":"https://avatars.githubusercontent.com/u/699596?v=3","gravatar_id":"","url":"https://api.github.com/users/scrapinghub","html_url":"https://github.com/scrapinghub","followers_url":"https://api.github.com/users/scrapinghub/followers","following_url":"https://api.github.com/users/scrapinghub/following{/other_user}","gists_url":"https://api.github.com/users/scrapinghub/gists{/gist_id}","starred_url":"https://api.github.com/users/scrapinghub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scrapinghub/subscriptions","organizations_url":"https://api.github.com/users/scrapinghub/orgs","repos_url":"https://api.github.com/users/scrapinghub/repos","events_url":"https://api.github.com/users/scrapinghub/events{/privacy}","received_events_url":"https://api.github.com/users/scrapinghub/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/scrapinghub/splash","description":"Lightweight, scriptable browser as a service with an HTTP API","fork":false,"url":"https://api.github.com/repos/scrapinghub/splash","forks_url":"https://api.github.com/repos/scrapinghub/splash/forks","keys_url":"https://api.github.com/repos/scrapinghub/splash/keys{/key_id}","collaborators_url":"https://api.github.com/repos/scrapinghub/splash/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/scrapinghub/splash/teams","hooks_url":"https://api.github.com/repos/scrapinghub/splash/hooks","issue_events_url":"https://api.github.com/repos/scrapinghub/splash/issues/events{/number}","events_url":"https://api.github.com/repos/scrapinghub/splash/events","assignees_url":"https://api.github.com/repos/scrapinghub/splash/assignees{/user}","branches_url":"https://api.github.com/repos/scrapinghub/splash/branches{/branch}","tags_url":"https://api.github.com/repos/scrapinghub/splash/tags","blobs_url":"https://api.github.com/repos/scrapinghub/splash/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/scrapinghub/splash/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/scrapinghub/splash/git/refs{/sha}","trees_url":"https://api.github.com/repos/scrapinghub/splash/git/trees{/sha}","statuses_url":"https://api.github.com/repos/scrapinghub/splash/statuses/{sha}","languages_url":"https://api.github.com/repos/scrapinghub/splash/languages","stargazers_url":"https://api.github.com/repos/scrapinghub/splash/stargazers","contributors_url":"https://api.github.com/repos/scrapinghub/splash/contributors","subscribers_url":"https://api.github.com/repos/scrapinghub/splash/subscribers","subscription_url":"https://api.github.com/repos/scrapinghub/splash/subscription","commits_url":"https://api.github.com/repos/scrapinghub/splash/commits{/sha}","git_commits_url":"https://api.github.com/repos/scrapinghub/splash/git/commits{/sha}","comments_url":"https://api.github.com/repos/scrapinghub/splash/comments{/number}","issue_comment_url":"https://api.github.com/repos/scrapinghub/splash/issues/comments/{number}","contents_url":"https://api.github.com/repos/scrapinghub/splash/contents/{+path}","compare_url":"https://api.github.com/repos/scrapinghub/splash/compare/{base}...{head}","merges_url":"https://api.github.com/repos/scrapinghub/splash/merges","archive_url":"https://api.github.com/repos/scrapinghub/splash/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/scrapinghub/splash/downloads","issues_url":"https://api.github.com/repos/scrapinghub/splash/issues{/number}","pulls_url":"https://api.github.com/repos/scrapinghub/splash/pulls{/number}","milestones_url":"https://api.github.com/repos/scrapinghub/splash/milestones{/number}","notifications_url":"https://api.github.com/repos/scrapinghub/splash/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/scrapinghub/splash/labels{/name}","releases_url":"https://api.github.com/repos/scrapinghub/splash/releases{/id}","created_at":"2013-05-20T21:20:33Z","updated_at":"2015-01-27T10:46:07Z","pushed_at":"2015-01-29T16:52:52Z","git_url":"git://github.com/scrapinghub/splash.git","ssh_url":"git@github.com:scrapinghub/splash.git","clone_url":"https://github.com/scrapinghub/splash.git","svn_url":"https://github.com/scrapinghub/splash","homepage":"","size":3701,"stargazers_count":173,"watchers_count":173,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":45,"mirror_url":null,"open_issues_count":43,"forks":45,"open_issues":43,"watchers":173,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/scrapinghub/splash/pulls/162"},"html":{"href":"https://github.com/scrapinghub/splash/pull/162"},"issue":{"href":"https://api.github.com/repos/scrapinghub/splash/issues/162"},"comments":{"href":"https://api.github.com/repos/scrapinghub/splash/issues/162/comments"},"review_comments":{"href":"https://api.github.com/repos/scrapinghub/splash/pulls/162/comments"},"review_comment":{"href":"https://api.github.com/repos/scrapinghub/splash/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/scrapinghub/splash/pulls/162/commits"},"statuses":{"href":"https://api.github.com/repos/scrapinghub/splash/statuses/99f28f4b59c36e5f6727414b6865de9ba717fdba"}}}}