Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How/why is “ *[attribute^="string" ” a valid querySelector? (JS bug?)

So, this might be a bug... I mistyped a CSS path to check for elements that had been processed to have a particular onclick function beginning "ajaxLoad("

document.querySelectorAll( 'a[onclick^="ajaxLoad("' )

As you can see, I forgot to close the attribute accessor, with ], like so :

document.querySelectorAll( 'a[onclick^="ajaxLoad(]"' )

Weirdly, it worked!

Edit - no I didn't, I actually ran the correct CSS selector:

document.querySelectorAll( 'a[onclick^="ajaxLoad("]' )

... but as mentioned in the comments apparently this further typo also works!

This is obviously invalid. I spotted it when I came to add another type of link, of class tc-link, and was wondering if I could just chain it like in CSS stylesheets as :

document.querySelectorAll( 'a[onclick^="ajaxLoad(", a.tc-link' )

The answer is that you can by closing that bracket, but not when this typo is left in.

Uncaught DOMException: Failed to execute 'querySelectorAll' on 'Document': 'a[onclick^="ajaxLoad(", a tc-link' is not a valid selector.

It works on ^=, $=, and *=, and from what I can see doesn't happen in Firefox or Opera (and I don't have any other browsers to test in).

I was thinking this was a language quirk at first but revised question: can anyone work out which level (DOM? V8? Er.. webkit? I don't know the ins and outs that well) of Javascript/browser code this relates to, and where it can get reported/fixed?

like image 380
Louis Maddox Avatar asked Mar 18 '15 11:03

Louis Maddox


People also ask

How do I use querySelector with data attribute?

Use the querySelector method to get an element by data attribute, e.g. document. querySelector('[data-id="box1"]') . The querySelector method returns the first element that matches the provided selector or null if no element matches the selector in the document.

Which is valid syntax for querySelector?

The querySelector() method returns the first element that matches a CSS selector. To return all matches (not only the first), use the querySelectorAll() instead. Both querySelector() and querySelectorAll() throw a SYNTAX_ERR exception if the selector(s) is invalid.

How do I get attributes in querySelector?

How it works: First, select the link element with the id js using the querySelector() method. Second, get the target attribute of the link by calling the getAttribute() of the selected link element. Third, show the value of the target on the Console window.

How does Javascript querySelector work?

The Document method querySelector() returns the first Element within the document that matches the specified selector, or group of selectors. If no matches are found, null is returned.


1 Answers

This is primarely opinion-based and is nowhere close to a definitive answer.

Browsers are EXTREMELY complex. Done! Nothing is predictable on them.

First, let's analyze a list of faulty selectors:

  • a[onclick^="ajaxLoad(" (missing ])
  • a[onclick^="ajaxLoad(]" (missing ])
  • a[onclick="" (missing ])
  • a[onclick="][onclick (missing "] or missing " and ] based on what you need)
  • a[onclick=""][onclick (missing ])
  • a[onclick=" (missing "])
  • a[onclick (missing ])
  • a:not([onclick] (missing ))
  • a:not([onclick (missing ]))
  • a:not([onclick=" (missing "]))
  • a:nth-child(5):not([onclick=" (missing "]))
  • a:-webkit-any(:not([onclick=" (missing "])))

So far, this is the list found. I can confirm that these work on Google Chrome 41.0.2272.89m on Windows 7.

Notice the pattern? It's simple: Chrome still can use there selectors to match the elements by filling with basic missing characters, but only at the end! What is missing is so predictable it doesn't require too much effort to fix. But not every selector can/will be 'fixed' (E.g.: a,, can be fixed by adding *).

This may be a bug or a feature (aka, an embarrassing bug submitted as a feature) to soften the eagerness of the CSS engine. This also affects jQuery since jQuery only uses Sizzle if document.querySelectorAll() doesn't exist or throws an exception.

With some time we can find many more.

Disclaimer:

This behaviour shouldn't be relied upon and may change in the future.
This is all based on invalid selectors and invalid syntax (like some IE CSS Hacks for older versions). ALL the working selectors on the list above are against the spec.

The 'unfixed' selector given as an example (a,) works in jQuery, but that is unrelated to this question. Essentially, jQuery will execute it as a.

like image 122
Ismael Miguel Avatar answered Oct 17 '22 07:10

Ismael Miguel