Phantomjs: querySelector(:nth-child) fails on second call

Created on 18 Sep 2013  路  17Comments  路  Source: ariya/phantomjs

This can be reproduced by querying for nth-child with a descendant, where the descendant doesn't exist for the first matching nth-child.

This should alert "http://fiddle.jshell.net/1, http://fiddle.jshell.net/1", but actually alerts "http://fiddle.jshell.net/1, null" on Phantom:

http://jsfiddle.net/GKb2g/5/

Probably something not being cleared up after the query.

stale

Most helpful comment

But it is occurring in PhantomJS 2.1.1.

All 17 comments

I have managed to replicate this issue, it happens when using :nth-child() in a document.querySelector API call.

Test Case

var page = require('webpage').create();
page.onConsoleMessage = function(msg) {
  console.log('[debug] ' + msg);
};
page.open('http://example.com', function (status) {
  if(status === 'success') {
    var actual = page.evaluate(function(){
      var first  = document.querySelector('p:nth-child(3) > a:nth-child(1)');
      var second = document.querySelector('p:nth-child(3) > a:nth-child(1)');
      return first === second;
    });
    if(!actual) {
      console.error('Expected First selector to equal the Second');
    } else {
      console.log('Passed');
    }
  }
  phantom.exit();
});

Actual response

Expected First selector to equal the Second

Expected response


This is a pretty unfortunate bug when you run into it, any timeline for when this might be fixed?

It appears to be an issue with Qt4 ported WebKit, it will not be resolved in the 1.9 version of PhantomJS. Hopefully Qt5 will have a newer WebKit port.

Any word on if this issue has been resolved?

I just ran into it and could use some help with possible solutions.

In CasperJS I worked around this by using the XPath selector instead of the CSS selector.

I just ran into this bug. Changing nth-child() to nth-of-type() fixed it for me.

Well, I thought just replacing nth-child() with nth-of-type() would always work. But it doesn't. In another case, I had to revert back to nth-child() and it WORKED!

I guess for now just try:

1) nth-child()
2) nth-of-type()
3) XPath selector (which i have not tried yet)

One hopefully will work for you until they fix it.

@mrfatboy what you suggest still doesn't work. I have created a test case that attempts your suggestion.

var page = require('webpage').create();
page.onConsoleMessage = function(msg) {
  console.log('[debug] ' + msg);
};
page.open('http://example.com', function (status) {
  if(status === 'success') {
    var actual = page.evaluate(function(){
      var selector = 'p:nth-child(3) > a:nth-child(1)';
      var first  = document.querySelector(selector);
      var second = document.querySelector(selector);
      if(second === null){
        second = document.querySelector(selector.replace('nth-child', 'nth-of-type'));
        if(second === null) {
          second = document.querySelector(selector.replace('nth-of-type','nth-child'));
        }
      }
      return first === second;
    });
    if(!actual) {
      console.error('Expected First selector to equal the Second');
    } else {
      console.log('Passed');
    }
  }
  phantom.exit();
});

result

$ phantomjs --version && phantomjs test.js
1.9.7
Expected First selector to equal the Second

@kylewelsby
More experimentation over the weekend revealed that method #1 and method #2 is not guaranteed. I did have to resort to method #3 (xpath) to have it work correctly. Very frustrating, I know.

Having same issue.
Version: 1.9.7

``` :html

**Javascript** (executed in Chrome console and PhantomJS Console)

document.querySelector("ul > li:nth-child(2) > label > a")

**Expected:**

4 stars:

**Actual:**

2 stars:
```

Hey guys, not sure if this is useful, but I also got the issue in a few examples. For instance, consider this example:

HTML code in selector_finder01.html:

<!DOCTYPE HTML>
<html>
    <body>
        <div></div>
        <div>
            <div>something 1</div>
            <div>something 2</div>
        </div>
    </body>
</html>

PhantomJS script:

var page = require("webpage").create();
page.open("file:///path_to_phantomscript/selector_finder01.html", function () {
    var element_text = page.evaluate(function () {
        return document.querySelector("body > div:nth-child(2) > div:nth-child(2)").textContent;
    });
    console.log(element_text);
    phantom.exit();
});

Result:

The execution of the PhantomJS script throws an exception, since the element returned by the querySelector Document method call returns null,
however it is expected that the CSS selector correctly matched the DIV element with text content "something 2".

If I use the CSS selector "body > div > div:nth-child(2)", the script return the expected value of "something 2".

Just came across this bug. I'm using 1.9.8.

In 1.9.8, querying something like "ul > li:nth-child(1), ul > li:nth-child(2)" returns only the first child.

Also came across this bug: .dashboard_item .title:nth-of-type(1) returns more than one element.

I can confirm PhantomJS 2.0.0 doesn't contain this bug anymore, and this can be marked as resolved.

But it is occurring in PhantomJS 2.1.1.

Due to our very limited maintenance capacity (see #14541 for more details), we need to prioritize our development focus on other tasks. Therefore, this issue will be automatically closed. In the future, if we see the need to attend to this issue again, then it will be reopened. Thank you for your contribution!

Was this page helpful?
0 / 5 - 0 ratings