GithubHelp home page GithubHelp logo

nwsapi's People

Contributors

alonidiom avatar dperini avatar eps1lon avatar exe-boss avatar ghostd avatar milahu avatar olegbarabanov avatar pkra avatar regseb avatar rondinelly avatar slavaleleka avatar willstott101 avatar zirro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

nwsapi's Issues

:scope selector direct children query is not working because of tag name resolution strategy

This was originally reported as part of the jsdom repo here.
I decided to try to fix it (because I had the exact same issue) and was able to track down the issue until here.

So here's the case: given the following DOM tree:

<div>
  <div class="ok"></div>
  <div class="ok">
    <div class="ko"></div>
  </div>
</div>

Getting a reference to the root <div> and doing the following query:

rootElement.querySelectorAll(':scope > div')

Doesn't only return the 2 expected "ok" divs but also the "ko" one.

Here's the full reproduction code allowing to easily switch between an ok and a ko case:

NW.Dom.install();

const SHOW_BUG = true;

const rootElementTagName = SHOW_BUG ? 'div' : 'main';

const html = `<${rootElementTagName}>
  <div class="ok"></div>
  <div class="ok">
    <div class="ko"></div>
  </div>
</${rootElementTagName}>`;

const dom = new window.DOMParser().parseFromString(html,'text/html');
const rootElement = dom.querySelector(rootElementTagName);
const queryResult = rootElement.querySelectorAll(':scope > div');

for (const element of queryResult) {
  console.log(element.className);
}

// This should always output:
// - ok
// - ok
//
// But the actual output is:
// - ok
// - ok
// - ko

And here's a fiddle hosting it.


I don't know this library codebase well, but I investigated a bit and I have the feeling that this is caused by the fact that this pattern : :scope > div is turned into a more generic one : div > div which is solved using a parent tag name resolution strategy and ultimately returns all the element globally matching this pattern: div > div, somewhat ignoring the element context.
I hope that this can help saving time to fix it.

I am trying to create a shadowRoot pseudoClass or operator, but nothing works.

Trying with this code, but returns a void array:

NW.Dom.registerSelector('shadow', /\:(shadow)/i, (function(global) {
    return function(match, source, mode, callback) {
        source = 'e=e.shadowRoot;' + source;
        return { 'source': source, 'status': true };
    }
})(this));
console.log(NW.Dom.select("body page-1:shadow footer", document));

Id starting with digit throws SyntaxError: '...' is not a valid selector

Hi,

when using an id which starts with a digit, nwsapi throws a "SyntaxError: '...' is not a valid selector", I guess because of the identifier regexp.

As mentioned in https://www.w3.org/TR/html4/types.html#type-id, ID and NAME tokens must begin with a letter ([A-Za-z]).
But, as described in https://html.spec.whatwg.org/multipage/dom.html#global-attributes:the-id-attribute-2, this constraint is not in place anymore for html5.
For this reason, could nwsapi be updated to take this into account maybe through an option?

Thanks,
Alessandro

Remove use of `Function` constructor

Hello, deno-dom uses this library to emulate the DOM in Deno. However, executing JavaScript from strings can result in possible insecure security flaws within code. As a result, secure web platforms such as Deno Deploy have disabled string code execution, which makes nwsapi.js unusable in secure contexts due to its use of the Function constructor for codegen in nwsapi.js, I am going to try and fix this later today after I get home but just going to create an issue in response to another issue in the deno-dom repo about deno-dom not working on Deno Deploy.

:scope pseudo-class fails for some XML documents with HTML-incompatible id

:scope fails to work with XML documents which have HTML-incompatible ids. Example:

doc = new DOMParser().parseFromString(`<?xml version="1.0" encoding="UTF-8"?><outer id='1a'><inner id='a'><inner></inner></inner></outer>`, "text/xml")

doc.firstChild.querySelectorAll(':scope > inner')  # WAI

This works on Chrome. However, using nwsapi fails:

NW.Dom.select(':scope inner', doc.firstChild)   # fails

The failure stems from :scope pseudo-class being replaced with element references which then create a selector that is invalid since HTML id attributes can't start with numbers: Uncaught DOMException: 'outer#1a inner' is not a valid selector

edit: hit enter too fast

2.0.9->2.1.0 upgrade breaks querySelector call with attribute selectors

'use strict';
const jsdom = require("jsdom");
const { JSDOM } = jsdom;

const dom = new JSDOM(`
<div aria-label="Account Information">
  <a href="https://www.example.com/foo" target="_blank">Foo</a>
</div>
`);

const els = dom.window.document.querySelectorAll(
  'div[aria-label] a[href="https://www.example.com/foo"]'
);
console.log(els);

With jsdom 13.2.0 and nwsapi 2.0.9, this code correctly finds one element. With nwsapi 2.1.0, this code fails to find any elements.

I noticed that nwsapi 2.1.0 fixes jsdom/jsdom#2403, which also has to do with attribute selectors, so I wonder if that fix might be related to this issue.

element selectors became case-sensitive in 2.2.1, in violation of spec

A simple repro:

<!doctype html>
<body>
<p></p>
<script src="src/nwsapi.js"></script>
<script>
NW.Dom.install();
document.body.innerHTML += [document.body.querySelector('P') != null, document.body.querySelector('p') != null].join(', ');
</script>

With 2.2.1 this prints false, true, when it should be true, true.

Per spec, "All Selectors syntax is ASCII case-insensitive".

I suspect this is due to #37 or one of the followup commits, though I haven't investigated.

(Discovered because this broke jsdom, which broke ecmarkup, which broke one of the JavaScript specifications.)

:not(:lang(...)) not supported?

I ran into some weird :not(...) selectors on Slack's homepage (in https://a.slack-edge.com/acdbf/style/rollup-marketing.css) that nwsapi doesn't support.

Repro:

new (require('jsdom').JSDOM)('').window.document.querySelector(':not(:lang(ja))')
SyntaxError: unknown pseudo-class selector ':not(:lang(ja))'
    at emit (/home/andreas/work/assetgraph/node_modules/nwsapi/src/nwsapi.js:529:17)
    at compileSelector (/home/andreas/work/assetgraph/node_modules/nwsapi/src/nwsapi.js:1171:17)
    at compile (/home/andreas/work/assetgraph/node_modules/nwsapi/src/nwsapi.js:718:19)
    at collect (/home/andreas/work/assetgraph/node_modules/nwsapi/src/nwsapi.js:1409:18)
    at _querySelectorAll (/home/andreas/work/assetgraph/node_modules/nwsapi/src/nwsapi.js:1349:18)
    at Object._querySelector [as first] (/home/andreas/work/assetgraph/node_modules/nwsapi/src/nwsapi.js:1283:14)
    at DocumentImpl.<anonymous> (/home/andreas/work/assetgraph/node_modules/jsdom/lib/jsdom/living/nodes/ParentNode-impl.js:65:42)
    at DocumentImpl.querySelector (/home/andreas/work/assetgraph/node_modules/jsdom/lib/jsdom/utils.js:123:45)
    at Document.querySelector (/home/andreas/work/assetgraph/node_modules/jsdom/lib/jsdom/living/generated/Document.js:689:45)

It works fine in Firefox and Chrome with document.querySelector.

can't match mixed-case tagName

Hi, I believe 32ac887 (line 826) makes it impossible to match a mixed-case tagName in an XML document. For example, if you have an element whose outerHTML is <w:rPr/>, that element's localName ends up being rPr, not rpr as 32ac887 seems to imply.

Issues with :focus-within

Hi there!

I've run into a few issues using the :focus-within selector with nwsapi v2.2.0.

Firstly, the current regex doesn't match correctly:

':focus-within'.match(/^:(?:(hover|active|focus|focus-within))(.*)/i)

Result:

[
  ':focus-within',
  'focus',
  '-within'
]

Changing the regex as follows, fixes this issue:

':focus-within'.match(/^:(?:(hover|active|focus-within|focus))(.*)/i)

Result:

[
  ':focus-within',
  'focus-within',
  ''
]

However, I haven't PR'd this because now there appears to be a recursion issue as my node process consumes 100% CPU and does not end (at least not for as long as I have been willing to wait).

I am using nwsapi as via jest (with vue-test-utils), so I'm unsure whether this issue is with nwsapi or not, and I'm not sure how to further debug it.

Any help would be appreciated!

Throw when repeated :scope

Basic info:

nwapi version: 2.2.0

Minimal reproduction case

Live example: https://jsbin.com/folowijuvi/edit?html,js,console,output

NW.Dom.install();
console.log(NW.Dom.select(':scope', document.body));
console.log(NW.Dom.select(':scope, :scope', document.body))
// []
// DOMException [SyntaxError]: unknown pseudo-class selector ':scope'
// emit@https://unpkg.com/[email protected]/src/nwsapi.js:565:17 
// compileSelector@https://unpkg.com/[email protected]/src/nwsapi.js:1292:21
// compile@https://unpkg.com/[email protected]/src/nwsapi.js:753:16
// collect@https://unpkg.com/[email protected]/src/nwsapi.js:1553:24
// _querySelectorAll@https://unpkg.com/[email protected]/src/nwsapi.js:1518:36

Notes

The real world use case was something like ':scope > span, :scope > div.

querySelector > E

Hi! This is my case:

...
<div id="my-id">
   <div>
      <a><span/></a>
      .... any number of a > span
      <span>
   </div>
   ... any number of the same structure
   <div>...</div>
</div>
...

I need separate values from a>span and div>span within function that holds ('#my-id')
I use function:

[...doc.querySelectorAll('#my-id > div')].map(row => {{
    rows: row.querySelectorAll('a > span') // ok, found all <a>
    root: row.querySelector(?)
}});

I have tried: > span, span:root, span:not(a > span) that are not valid and span:last-child,span:last-of-type that return span inside first tag

How do I find the tag inside the row?

Attribute selector [data-x='],'] not recognized as valid selector

NWSAPI incorrectly reports the selector [data-x='],'] (selecting elements with data-x attribute value of exactly ], - eg. <div data-x='],'></div>) as invalid. This is in fact a valid selector (at least in as much as browsers seem to recognize it just fine - I've not dug into the CSS grammar to check if it is).

Neither ] nor , alone seem to trigger the invalid selector error, and it is possible to work around it by escaping both characters ], as \]\, in the value.

JSFiddle repro: https://jsfiddle.net/2wemxrp3/

[XML] Selector with two elements, one capitalized

I found a difference between nwsapi and browsers (Firefox and Chromium). For an XML document with a capitalized element, the querySelector() method doesn't work when searching by putting two elements in the selector.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Test case</title>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/src/nwsapi.js" onload="NW.Dom.install()"></script>
  </head>
  <body>
    <script>
        onload = function() {
            const xml = '<?xml version="1.0"?><Foo><bar></bar></Foo>';
            const dom = new window.DOMParser().parseFromString(xml, 'text/xml');
            console.log('0. Expected [Foo]', dom.querySelectorAll('Foo')); // Passed
            console.log('1. Expected []',    dom.querySelectorAll('foo')); // Passed
            console.log('2. Expected [bar]', dom.querySelectorAll('bar')); // Passed
            console.log('3. Expected []',    dom.querySelectorAll('foo bar')); // Passed
            console.log('4. Expected [bar]', dom.querySelectorAll('Foo bar')); // Failed!

            const xml2 = xml.toLowerCase();
            const dom2 = new window.DOMParser().parseFromString(xml2, 'text/xml');
            console.log('10. Expected [bar]', dom2.querySelectorAll('bar')); // Passed
            console.log('11. Expected []',    dom2.querySelectorAll('Bar')); // Passed
            console.log('12. Expected [bar]', dom2.querySelectorAll('foo bar')); // Passed
            console.log('13. Expected []',    dom2.querySelectorAll('Foo bar')); // Failed!
            console.log('14. Expected []',    dom2.querySelectorAll('FOO bar')); // Failed!
            console.log('15. Expected []',    dom2.querySelectorAll('foo BAR')); // Passed
            console.log('16. Expected []',    dom2.querySelectorAll('FOO BAR')); // Passed
        };
    </script>
  </body>
</html>

namespaces tag names not matched

@dperini This looks great, but the selector issues for XML seem to be the as in nwmatcher.

This works::

let parser = new window.DOMParser()
let string = `<?xml version="1.0"?><cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:title></dc:title></cp:coreProperties>`
let dom = parser.parseFromString(string, 'text/xml')
let el = dom.querySelector('coreProperties')

But if one replaces the querySelector with the one from nwsapi, it does not::

NW.Dom.install()
let parser = new window.DOMParser()
let string = `<?xml version="1.0"?><cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:title></dc:title></cp:coreProperties>`
let dom = parser.parseFromString(string, 'text/xml')
let el = dom.querySelector('coreProperties')

What does however work is::

dom.querySelector('cp\\:coreProperties')

Which in turn does not work with the native querySelector found in browsers.

Same behavior as in nwmatcher seen in jsdom/jsdom#2159

Support :placeholder-shown pseudo-class

The :placeholder-shown pseudo-class has pretty good support in recent browsers. It matches <input> elements which are currently showing their placeholder text. This can probably be implemented by checking that the element has a placeholder, but isn't currently focused.

Specification: https://drafts.csswg.org/selectors-4/#placeholder

Test: https://github.com/w3c/web-platform-tests/blob/master/html/semantics/selectors/pseudo-classes/placeholder-shown-type-change.html

In unit tests: RangeError: Invalid string length

While using react testing library that uses this library, I have encountered a difficult-to-find error when running unit tests that were just breaking and showing the following message:

node_modules/nwsapi/src/nwsapi.js:893
      source = ‘n=e;while((e=e.parentElement)){’ + source + ‘}e=n;’;

After hours of investigation, I have found out that one of the React styled components I was using had a tiny mistake in its styles.
Something like:

  tbody th {
    vertical-align: middle;

    > span {
      display: inline-block;
      padding: 0;
    }
  }ç

Where a character was out of the parenthesis.

Whitespace around operator breaks nth-child selectors

Given this html page:

<!DOCTYPE html>
<script type="text/javascript" src="src/nwsapi.js"></script>
<div>
  <p>first</p>
  <p>second</p>
  <p>third</p>
</div>

The selector p:nth-child(2n + 1) only works if SIMPLENOT is false:

image

The same selector without whitespace, p:nth-child(2n+1), works in both modes. The spec allows whitespace, so ideally both selectors should always work.

In addition, prettier seems to autoformat CSS selectors with spaces in this situation. So this bug leads to a sad case where autoformatting your code with prettier can cause unit tests to break in the Jest -> JSDOM -> NWSAPI stack (or anything else relying on JSDOM to run tests).

Thanks for the help!

Edit: I believe the issue goes beyond SIMPLE_NOT, for example, p:nth-child(2n - 1) doesn't work in either mode.

It does not handle escape backslash for class names correctly

Hello! Thanks for this amazing work!

I found that the nwsapi tries to select pseudo-classes when the given class name includes : with preceding \. And this naming pattern is used by famous CSS library tailwindCSS. Is there way to handle correctly?

Thank you!

Query selector, use of `~` in `:not()` throws

import { JSDOM } from 'jsdom'

const doc = new JSDOM(`
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
</head>
<body>
</body>
</html>
`).window.document

doc.querySelector('.js-sns-icon-container ~ h2 ~ h2 ~ .spaceit_pad:not(.js-sns-icon-container ~ h2 ~ h2 ~ h2 ~ .spaceit_pad)')

throws

'.js-sns-icon-container ~ h2 ~ h2 ~ .spaceit_pad:not(.js-sns-icon-container ~ h2 ~ h2 ~ h2 ~ .spaceit_pad)' is not a valid selector

Trying to query for .js-sns-icon-container ~ h2 ~ h2 ~ .spaceit_pad:not(.js-sns-icon-container ~ h2 ~ h2 ~ h2 ~ .spaceit_pad) in browsers work completly fine (Tried in chrome and FF).

Tag with an uppercase letter is not working as expected in XML

This was originally reported as part of the jsdom repo here.
I decided to try to fix it (because I had the exact same issue) and was able to track down the issue until here.

So here's the case: given the following XML DOM tree:

<root>
  <aB>
    <c></c>
  </aB>
  <cd>
    <e></e>
  </cd>
</root>

This query: aB * doesn't return anything while it should match the <c> element.

Here's the full reproduction code:

NW.Dom.install();

const xml = `
<root>
  <aB>
    <c></c>
  </aB>
  <cd>
    <e></e>
  </cd>
</root>
`;

const dom = new window.DOMParser().parseFromString(xml, 'text/xml');
const ko = dom.querySelectorAll('aB *').length; // 0 (should be 1)
const ok = dom.querySelectorAll('cd *').length; // 1
console.log({ko,ok});

And here's a fiddle hosting it.


I don't know this library codebase well, but I investigated a bit and I have the feeling that this is caused by the fact that the selector is converted to lower case while the element localName is not.
Hence the missing match in the compiled resolver code.

What I also noticed is that if you parse the same code as HTML, with:

const dom = new window.DOMParser().parseFromString(xml, 'text/xml');

It works as expected, I guess because all the tags are automatically converted to lower case.

DocumentFragments do not implement getElementById, but nwsapi assumes they do

     TypeError: fragment.getElementById is not a function
      at hasDuplicateId (node_modules\nwsapi\src\nwsapi.js:271:34)
      at byId (node_modules\nwsapi\src\nwsapi.js:301:33)
      at node_modules\nwsapi\src\nwsapi.js:252:61
      at Object.Resolver [as factory] (eval at compile (node_modules\nwsapi\src\nwsapi.js:687:17), <anonymous>:3:71)
      at Object._querySelectorAll [as select] (node_modules\nwsapi\src\nwsapi.js:1287:23)
      at DocumentFragmentImpl.<anonymous> (lib\jsdom\living\nodes\ParentNode-impl.js:68:24)

Here the last line in the stack trace is essentially

  const list = matcher.select(selectors, someDocumentFragment);

':focus-visible' is not supported, yet claims to be in the wiki

I ran into an issue where I was using jsdom which uses nwsapi for matching selectors and it was giving me the error SyntaxError: ':focus-visible' is not a valid selector. It doesn't seem like I should be getting this error because in the wiki for nwsapi, it says that the :focus-visible is supported.

Then I looked through the nwsapi repo and didn't see focus-visible where I thought it should exist. Here with the other user actions: https://github.com/dperini/nwsapi/blob/master/src/nwsapi.js#L83

It would be great if this could be supported. Alternatively, the documentation could be updated explaining that it is actually not supported and why.

Reproduce:

<script
  type="text/javascript"
  src="https://cdn.jsdelivr.net/npm/[email protected]/src/nwsapi.js"
></script>
<script>
  NW.Dom.match(":focus-visible", document, () => {});
</script>

Results in Uncaught DOMException: ':focus-visible' is not a valid selector.

On another note, it looks like focus-within throws the same error, even though it looks like it is available in the source code. Not sure why that would be though.

Exception occurs when using element.matches

element.matches can throw an unexpected error for certain selectors.

Here is an example to reproduce the issue in the browser (assuming nwsapi.js is included in a <script> tag):

const div = document.createElement('div');
div.innerHTML = '<div class="b"><div class="c"></div></div>';
//document.documentElement.appendChild(div); // Doesn't matter if this is executed or not
const c = div.querySelector('.c');
const selector = '.a:nth-last-of-type(1) .b .c';
console.log(c.matches(selector)); // Okay with native DOM
console.log(NW.Dom.match(selector, c)); // Throws
Uncaught TypeError: Cannot read property 'parentElement' of null
    at Array.Resolver (eval at compile (nwsapi.js:768), <anonymous>:3:129)
    at match_assert (nwsapi.js:1351)
    at Object._matches [as match] (nwsapi.js:1415)

Full CSS3 namespace support

nwsapi is a brilliant piece of work - wow!

Is there any interest in adding full CSS3 namespace support? This would include adding support for selectors that contain namespaced prefixes such as:

*|myelem (this is actually supported natively by querySelector/querySelectorAll native methods in browsers)
myns|* (unsupported natively)
myns|myelem (unsupported natively)
*[*|myattr] (supported natively)
*[myns|*] (unsupported natively)
*[myns|myattr] (unsupported natively)

Note that what I'm asking about here is not solved by the simplistic approach of "just use an escaped : character". True namespace support requires being able to resolve namespaces based on the location of the element in the DOM, what namespaces are defined in the markup and how namespace prefixes are associated to a URI.

The document.evaluate XPath call provides an example of one way this functionality might be provided. It uses a 'namespace resolver' to assist the call in determining the namespace. See the section "Implementing a User Defined Namespace Resolver" here:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_using_XPath_in_JavaScript#Implementing_a_User_Defined_Namespace_Resolver

I currently use a very old jQuery plugin that provides true namespace support to jQuery, but it hasn't been updated in a long time and is only usable with the jQuery 1.X series. Replacing that with nwsapi would be very nice indeed :-).

Thanks!

:focus doesn't work with shadow DOM

See https://github.com/web-platform-tests/wpt/blob/7d99d2ca0def8468acfaee9aa15076a68efb21ca/shadow-dom/focus/focus-selector-delegatesFocus.html. Essentially, with the following setup:

<!DOCTYPE html>
<body>
<script>
  const host = document.createElement("div");
  host.attachShadow({ mode: "open" });
  document.body.appendChild(host);
  
  const shadowChild = document.createElement("div");
  shadowChild.innerText = "foo";
  shadowChild.tabIndex = 0;
  host.shadowRoot.appendChild(shadowChild);

  shadowChild.focus();
  console.log(NW.Dom.match(shadowChild, ":focus"), "element in shadow tree matches :focus");
  console.log(NW.Dom.match(host, ":focus"), "host matches :focus");
</script>

However, currently only the latter returns true, since document.activeElement is host. (However, host.shadowRoot.activeElement is shadowChild.)

The linked file has more examples, some using <slot>.

Throw when repeated complex select

Basic info:

  • nwapi version: 2.2.0

Minimal reproduction case

Live example: jsbin

NW.Dom.install();
NW.Dom.select('.foo, .foo, .bar', document.body);  // pass
NW.Dom.select('.foo, .foo, .bar', document.body); // error

// nwsapi.js:1450 Uncaught TypeError: Cannot read property '0' of undefined
//    at Object._querySelectorAll [as select]

Observations

This is a real conner case, this issue only happens when there is a duplicate class selector and different class selector in a compound selector and when the selector runs multiple times. Context in the original issue.

Support for :scope

Hello,

More a question than an issue: I'm going to take a look at adding tests for the :scope pseudo-class - cf. jsdom/jsdom#2028 - however from what I see in the test/scope/*.html files it seems that nothing is automated.
Should I setup some automation (with whichever test framework you want) or do I just add new tests following the same format with console logs?

Thanks

Invalid selector parsed as valid

I'm using [email protected], which has [email protected] as a dependency. The following script runs without errors (it outputs true):

const { JSDOM } = require("jsdom");

const dom = new JSDOM(`
<!DOCTYPE html>
<body>
  <div class="section">
    <p class="text">
      <span class="important">IMPORTANT</span>
    </p>
  </div>
</body>
`);

const el = dom.window.document.querySelector(".section > > .important");
console.log(el.nodeName === "SPAN");

However, in a browser, .section > > .important is an invalid selector, as shown by this JS Bin. It throws a DOMException.

I suppose the issue is that the space between the two child combinators is converted to a wildcard selector, but that creates an inconsistency between different selector engines and environments.

jsdom should be in devDependencies

In the latest release you added jsdom as a dependency, but as it is only used for tests it should a dev dependency to avoid any package user installing it.

infinite recursion on invalid selector _:-ms-fullscreen

function compileSelector in nwsapi.js

source = 'n=e;while((e=e.parentElement)){' + source + '}e=n;';
source grows to infinite length, until RangeError: Invalid string length

normal source.length are around 1000 bytes
with infinite loop, source.length grows to the maximum string length of 1GB

the selector _:-ms-fullscreen comes from deepl.com/css/lmt.$d783c6.css
.lmt--web .lmt__side_container--target .lmt__ad_charLimit_container _:-ms-fullscreen

the problem is

        default:
          emit('\'' + selector_string + '\'' + qsInvalid);
          break;
        }
        // end of switch symbol

which only breaks the switch (symbol) { block, but not the while (selector) { loop -> deadloop

the parser should seek to the next comma or to end of selector string

workarounds:

class CustomResourceLoader extends jsdom.ResourceLoader {
  fetch(url, options) {

    // ignore all styles
    if (url.endsWith('.css')) {
      return Promise.resolve(Buffer.from(''));
    }

    // patch style
    if (url == 'https://example.com/path/to/style.css')) {
      var str = require('fs').readFileSync('style.patched.css', 'utf8');
      return Promise.resolve(Buffer.from(str));
    }

    return super.fetch(url, options);
  }
}
const resourceLoader = new CustomResourceLoader();
const dom = new jsdom.JSDOM('', { resources: resourceLoader });

Pass remaining Web Platform Tests for selectors

nwsapi is nearly passing all Web Platform Tests that browsers do, which is very exciting. Since these tests are used by browsers to ensure that they are compatible with each other, it would be excellent if it could pass the final ones as well. These are the last tests from the dom/nodes/ directory which pass in browsers, but fail in nwsapi:

dom/nodes/ParentNode-querySelector-All.html:

  • Document.querySelectorAll: ID selector, matching multiple elements with duplicate id: #id-li-duplicate
  • Fragment.querySelectorAll: Namespace selector, matching element with any namespace: #any-namespace *|div
  • Fragment.querySelectorAll: Namespace selector, matching div elements in no namespace only: #no-namespace |div
  • Fragment.querySelector: Namespace selector, matching div elements in no namespace only: #no-namespace |div

dom/nodes/Element-closest.html:

  • Element.closest with context node 'test4' and selector 'div > :scope'

Let me know if you have any questions about the tests.

micro optimization: reuse resolvers for pseudo elements

edit: full revoke. see PR #40

edit: partial revoke: nwsapi does use different resolvers
for base-element vs pseudo-element:

if (!(e.nodeType == 1)) {

.... this condition is added for the selector body>div::after
compared to body>div

nodeType 1 is ELEMENT_NODE

node types in jsdom
module.exports = Object.freeze({
  ELEMENT_NODE: 1,
  ATTRIBUTE_NODE: 2,
  TEXT_NODE: 3,
  CDATA_SECTION_NODE: 4, // historical
  ENTITY_REFERENCE_NODE: 5, // historical
  ENTITY_NODE: 6, // historical
  PROCESSING_INSTRUCTION_NODE: 7,
  COMMENT_NODE: 8,
  DOCUMENT_NODE: 9,
  DOCUMENT_TYPE_NODE: 10,
  DOCUMENT_FRAGMENT_NODE: 11,
  NOTATION_NODE: 12 // historical
});

--

currently nwsapi compiles different resolvers
for (base-) elements and pseudo-elements

for example it compiles two different resolvers
for the selectors div and div::before

but it should compile only one resolver
since all resolvers return the same (base-) element

so, selectors in function _matches(selectors, element, callback)
should be processed with something like

const baseSel = selectors.replace(/::[a-z-]+/gi, '')

or more verbose

const pseudoElementNames = [
  'after',
  'backdrop'
  'before',
  'cue',
  'cue-region',
  'first-letter',
  'first-line',
  'grammar-error',
  'marker',
  //'part()',
  'placeholder',
  'selection',
  //'slotted()',
  'spelling-error',
];

const re = new RegExp('::('+pseudoElementNames.join('|')+')', 'gi')
const baseSel = selectors.replace(re, '')

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.