bootstrap icon indicating copy to clipboard operation
bootstrap copied to clipboard

SyntaxError: Failed to execute 'querySelector' on 'Element': '#div-2.1' is not a valid selector

Open larseggert opened this issue 3 years ago • 8 comments

Prerequisites

Describe the issue

#35566 didn't fix things for all weird IDs. The test case addition below causes the error in the issue title.

Reduced test cases

diff --git a/js/tests/unit/scrollspy.spec.js b/js/tests/unit/scrollspy.spec.js
index c7951e6..704b52a 100644
--- a/js/tests/unit/scrollspy.spec.js
+++ b/js/tests/unit/scrollspy.spec.js
@@ -341,11 +341,13 @@ describe('ScrollSpy', () => {
           '  <ul class="nav">',
           '    <li class="nav-item"><a class="nav-link" id="a-1" href="#div-1">div 1</a></li>',
           '    <li class="nav-item"><a class="nav-link" id="a-2" href="#div-2">div 2</a></li>',
+          '    <li class="nav-item"><a class="nav-link" id="a-2.1" href="#div-2.1">div 2</a></li>',
           '  </ul>',
           '</nav>',
           '<div class="content" style="overflow: auto; height: 50px">',
           '  <div id="div-1" style="height: 100px; padding: 0; margin: 0">div 1</div>',
           '  <div id="div-2" style="height: 200px; padding: 0; margin: 0">div 2</div>',
+          '  <div id="div-2.1" style="height: 200px; padding: 0; margin: 0">div 2.1</div>',
           '</div>'
         ].join('')

What operating system(s) are you seeing the problem on?

macOS

What browser(s) are you seeing the problem on?

Firefox

What version of Bootstrap are you using?

v5.2.3

larseggert avatar Jan 11 '23 14:01 larseggert

@larseggert this is weird...

did not take the time to look at, but If I copy-paste:

const parseSelector = selector => {
   if (selector && window.CSS && window.CSS.escape) {
     // document.querySelector needs escaping to handle IDs (html5+) containing for instance /
     selector = selector.replaceAll(/#([^\s"#']+)/g, (match, id) => '#' + CSS.escape(id))
   }

   return selector
 }

in my JS Console in Firefox, and then I type:

parseSelector("#div-2.1")
"#div-2\\.1" 

=> Looks like the correct result to me

pierresouchay avatar Jan 11 '23 16:01 pierresouchay

Hm. Apply the patch and run the tests? That should recreate the issue. (Maybe that function isn't called?)

larseggert avatar Jan 11 '23 17:01 larseggert

Here is the test failure I get with the patch above:

Chrome Headless 109.0.5414.87 (Mac OS 10.15.7) ScrollSpy constructor should add the active class to the correct element FAILED
	SyntaxError: Failed to execute 'querySelector' on 'Element': '#div-2.1' is not a valid selector.
	error properties: Object({ code: 12, INDEX_SIZE_ERR: 1, DOMSTRING_SIZE_ERR: 2, HIERARCHY_REQUEST_ERR: 3, WRONG_DOCUMENT_ERR: 4, INVALID_CHARACTER_ERR: 5, NO_DATA_ALLOWED_ERR: 6, NO_MODIFICATION_ALLOWED_ERR: 7, NOT_FOUND_ERR: 8, NOT_SUPPORTED_ERR: 9, INUSE_ATTRIBUTE_ERR: 10, INVALID_STATE_ERR: 11, SYNTAX_ERR: 12, INVALID_MODIFICATION_ERR: 13, NAMESPACE_ERR: 14, INVALID_ACCESS_ERR: 15, VALIDATION_ERR: 16, TYPE_MISMATCH_ERR: 17, SECURITY_ERR: 18, NETWORK_ERR: 19, ABORT_ERR: 20, URL_MISMATCH_ERR: 21, QUOTA_EXCEEDED_ERR: 22, TIMEOUT_ERR: 23, INVALID_NODE_TYPE_ERR: 24, DATA_CLONE_ERR: 25 })
	    at Object.findOne (js/src/dom/selector-engine.js:41:44 <- js/tests/unit/scrollspy.spec.js:9260:46)
	    at ScrollSpy._initializeTargetsAndObservables (js/src/scrollspy.js:211:48 <- js/tests/unit/scrollspy.spec.js:15411:76)
	    at ScrollSpy.refresh (js/src/scrollspy.js:91:10 <- js/tests/unit/scrollspy.spec.js:15227:12)
	    at new ScrollSpy (js/src/scrollspy.js:73:10 <- js/tests/unit/scrollspy.spec.js:15207:12)
	    at js/tests/unit/scrollspy.spec.js:355:27 <- js/tests/unit/scrollspy.spec.js:15743:29
	    at new Promise (<anonymous>)
	    at UserContext.<anonymous> (js/tests/unit/scrollspy.spec.js:338:14 <- js/tests/unit/scrollspy.spec.js:15740:16)
	    at <Jasmine>
```	    

larseggert avatar Jan 12 '23 13:01 larseggert

OK, I'm not familiar with the bootstrap code, but to me it looks like scrollspy uses various SelectorEngine functions (find, etc.) that don't seem to call parseSelector at all?

larseggert avatar Jan 12 '23 13:01 larseggert

I have a similar problem but with a tab linking to an external PDF file, using the "file.pdf#page=10" format.

<a href="http://example.com/document.pdf#page=10" target="_blank" class="nav-link">External link</a>

I got JS errors:

Uncaught DOMException: Document.querySelector: '#page=10' is not a valid selector

neurotools avatar Apr 09 '23 03:04 neurotools

+1. I am also seeing this issue on Bootstrap v5.2.3, running Microsoft Edge v112 on Windows 11.

<h2 id="2-partition-normalized-cut">2-partition: Normalized Cut</h2>

causes the error

Uncaught DOMException: Failed to execute 'querySelector' on 'Element': '#2-partition-normalized-cut' is not a valid selector.
    at Object.findOne (https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js:6:10283)
    at Be._initializeTargetsAndObservables (https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js:6:53059)
    at Be.refresh (https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js:6:51311)
    at new Be (https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js:6:51184)
    at Be.getOrCreateInstance (https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js:6:8552)
    at https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js:6:54113
    at i (https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js:6:4608)

It seems like #34412 (which was supposed to be closed by #35566) is actually still not solved.

chrisyeh96 avatar Apr 17 '23 08:04 chrisyeh96

Can confirm on 5.3.2.

Patching SelectorEngine.findOne() like so fixes (that part of...) scrollspy for me and my #2-foo-bar IDs. (not checked for side-effects!)

    findOne(selector, element = document.documentElement) {
-      return Element.prototype.querySelector.call(element, selector);
+      return Element.prototype.querySelector.call(element, parseSelector(selector));
    },

InsanePrawn avatar Oct 14 '23 01:10 InsanePrawn

the SelectorEngine.findOne() expects a css selector as valid parameter.

Scrollspy, the caller simply does not escape it: https://github.com/twbs/bootstrap/blob/0a005b36048d549057f8b551b2d19ca043a9a4c0/js/src/scrollspy.js#L213

It seams of but maybe someone want to find one element #theId.myClass => SelectorEngine should not try to escape it.

Zetanova avatar May 14 '25 17:05 Zetanova