window.callPhantom not working when child frame navigates to new location #11204

Open
rsussland opened this Issue Apr 3, 2013 · 2 comments

Comments

Projects
None yet
3 participants

on phantomjs 1.9.0 linux x64

I have an index.html page that contains an iframe with source "frame1.html". The iframe contains a link which, when clicked, loads "frame2.html". I have a phantomjs script which switches to the child frame, clicks the link, and waits for load to complete. Then it attempts to evaluate "window.callPhantom("hello")" on the child frame. The evaluation fails with an 'undefined is not a function' error. I expect the evaluation to succeed. Note that this problem is specific to window.callPhantom. Normal javascript injected into the child frame executes successfully.

Here is the script and html pages:

phantom script

//c.f. http://stackoverflow.com/questions/9246438/how-to-submit-a-form-using-phantomjs

var page = require('webpage').create();
var busy = false;
var index = 0;

page.onConsoleMessage = function(msg) {
    console.log(msg);
};

page.onCallback = function(data) {
    console.log("CALLBACK: " + data);
};

page.onLoadStarted = function() {
  busy = true;
  console.log("load started");
};

page.onLoadFinished = function() {
  busy = false;
  console.log("load finished");
};

var steps = [
  //load start page
  function() {
    page.open("http://localhost:8000/simple_frame/");
  },

  //switch to frame and click link
  function() {
    page.switchToFrame(0);
    page.evaluate(function() {

        var links = document.getElementsByTagName("a");
        if (links.length > 0) {
            var ev = document.createEvent("MouseEvents"); //from pjs examples
            ev.initEvent("click", true, true);
            links[0].dispatchEvent(ev);
        };
    });
    }, 

    function() {
        //Report
        page.switchToMainFrame();
        page.switchToFrame(0);
        page.evaluate(function() {
            window.callPhantom("hello");  //this fails
        });
    } 

];


interval = setInterval(function() {
  if (!busy && typeof steps[index] == "function") {
    console.log("step " + (index + 1));
    steps[index]();
    index++;
  }
  if (typeof steps[index] != "function") {
    console.log("test complete!");
    phantom.exit();
  }
}, 50);

output of script:

step 1
load started
load finished
step 2
load started
load finished
step 3
TypeError: 'undefined' is not a function (evaluating 'window.callPhantom("hello")')

  phantomjs://webpage.evaluate():2
  phantomjs://webpage.evaluate():3
  phantomjs://webpage.evaluate():3
test complete!

simple website:

index.html

<html>
<head>Simple frame navigation test</head>
<body>
    <h2>Here is a frame<h2>
        <iframe src="frame1.html"> </iframe>
</body>
</html>
</code>

#### frame1.html

<code>
<html>
<head></head>
<body>
    <h2>Inside frame1<h2>
        <a href="frame2.html">link</a>
</body>
</html>

frame2.html

<html>
<head></head>
<body>
    <h2>Inside frame2<h2>

</body>
</html>
Collaborator

JamesMGreene commented Apr 3, 2013

@detro did some specific work to inject things into a frame's window when the frame is created. However, I am guessing that URL navigation within the frame doesn't re-trigger that "created" signal/event, so perhaps we need to add the same injection code into a post-navigation hook as well.

Collaborator

JamesMGreene commented Apr 3, 2013

P.S. This issue is originated from the following mailing list thread: https://groups.google.com/d/topic/phantomjs/4fHf8amnmY4/discussion

In that topic, @rsussland mentioned:

"[I]t is only window.callPhantom which is failing. When I replace the last step with [a return statement], then it succeeds.

Just to reiterate and comment on this statement specifically, this is because the window.callPhantom method needs to be injected into the frame whereas the ability to return something from an eval is always available.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment