trifleJS icon indicating copy to clipboard operation
trifleJS copied to clipboard

WebPage.onInitialized is not called when set

Open tejacques opened this issue 9 years ago • 7 comments

Bug

Setting the onInitialized function does not cause it to be called, as the check to call it is currently in the WebPage constructor (init function of WebPage.js).

Steps to Reproduce

run:

TrifleJS.exe onInitialized.js

onInitialized.js:

var page = webpage = require('webpage').create();
page.onInitialized = function() {
    console.log('should log');
};
// any url
page.open('about:blank');

Expected Output (PhantomJS)

should log

Actual Output (TrifleJS)

The PhantomJS spec says (http://phantomjs.org/api/webpage/handler/on-initialized.html):

This callback is invoked after the web page is created but before a URL is loaded. The callback may be used to change global objects.

The logic should be moved into the open function. This is actually a bit trickier than it looks at first glance because the PhantomJS spec allows you to change global objects on the page, which the .NET client will clear on calls to navigate. A callback needs to be set up to invoke the supplied function at the proper time after creating the page.

tejacques avatar Feb 22 '15 06:02 tejacques

I think I've got something working for this using the Navigated event. I'm not sure if it's spec equivalent to PhantomJS because it won't fire on reload, but I'll try to do some testing and submit a PR.

tejacques avatar Feb 23 '15 05:02 tejacques

There's actually another bug related to this. The toolset added to the window (json2 and ie tools) aren't actually available until the page onload event is fired. In PhantomJS they are available immediately because they are inserted when the page is created.

This can be fixed very easily by moving the AddToolset() call from DocumentCompleted to Navigated. The unhandled error tracking should also be moved.

tejacques avatar Feb 23 '15 07:02 tejacques

Hi @tejacques, like your fix. Will get to it ASAP.

sdesalas avatar Mar 08 '15 02:03 sdesalas

HI @tejacques,

Added a fix for this bug. Had to call page.onInitialized during the first part of DocumentCompleted event (instead of Navigated, but a bit earlier than before as I'm not waiting for all other js/css/img resources via window.onload). Reason for this is that I couldn't get access to global variables using page.evaluate during Navigated.

Thanks for your help and for the detailed test example.

My unit tests are running ok now. Let me know how you go.

sdesalas avatar Mar 08 '15 14:03 sdesalas

Btw. I noticed that if I move 'onInitialized' to the 'Navigated' browser event I can write to global context on the webpage (but not read as the DOM is not available yet).. might consider moving functionality there if PhantomJS behaves the same way.

sdesalas avatar Mar 09 '15 01:03 sdesalas

In phantomJS onInitialized is called before the DOM is ready or any JS executes on the page.

Here's an example to test with:

TestPage.html

<!DOCTYPE html>
<html>
<head>
    <title>Test Page</title>
</head>
<body>
    <script>
        callPhantom({ hello: 'from script tag' });
        window.onload = function () {
            callPhantom({ hello: 'from onload' });
        }
    </script>
</body>
</html>

TestScript.js

var webPage = require('webpage');
var page = webPage.create();
page.onInitialized = function () {
    console.log("Initialized");
}
page.onCallback = function(data) {
    console.log('CALLBACK: ' + JSON.stringify(data));
  // Prints 'CALLBACK: { "hello": "world" }'
};
page.onConsoleMessage = function (msg) {
    console.log(msg);
};
page.evaluate(function () {
    callPhantom({ hello: 'world' });
});
page.open('http://localhost:port/path/to/TestPage.html', function (status) {
    phantom.exit();
});

PhantomJS Output:

>phantomjs path/to/TestScript.js
Initialized
CALLBACK: {"hello":"world"}
Initialized
CALLBACK: {"hello":"from script tag"}
CALLBACK: {"hello":"from onload"}

TrifleJS Output:

>trifleJS.exe path/to/TestScript.js
CALLBACK: {"hello":"world"}
CALLBACK: {"hello":"from script tag"}
Initialized
CALLBACK: {"hello":"from onload"}

Currently, TrifleJS isn't calling onInitialized at all unless a page is loaded, and onInitialized is called after the page runs, but before onload.

tejacques avatar Mar 09 '15 05:03 tejacques

Hiya,

Thanks for the great test example, I've used it to determine the load order for main lifecycle events (including onLoadStarted and onLoadFinished) and got the following from PhantomJS:

onInitialized
onCallback: beforeopen
onLoadStarted
onInitialized
onCallback: script
onCallback: onload
onLoadFinished
page.open

I've replicated this order (except for the first event) in my unit tests so I dont break it later.

The event missing is the onInitialized event called at the very beginning (during page.evaluate() and before page.open()). My feeling with this one is that I'd rather leave it for now as I'll break a few things if I try to postpone initialization (before opening a remote page) in the same way.

sdesalas avatar Mar 11 '15 13:03 sdesalas