Skip to content

Commit c039e52

Browse files
asamuzaKdomenic
authored andcommitted
Switch from nwsapi to dom-selector
1 parent b677627 commit c039e52

7 files changed

Lines changed: 171 additions & 133 deletions

File tree

Lines changed: 80 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,92 @@
11
"use strict";
22

3-
const nwsapi = require("nwsapi");
4-
3+
const domSelector = require("@asamuzakjp/dom-selector");
4+
const DOMException = require("../generated/DOMException");
55
const idlUtils = require("../generated/utils");
66

7-
function initNwsapi(node) {
8-
const { _globalObject, _ownerDocument } = node;
9-
10-
return nwsapi({
11-
document: idlUtils.wrapperForImpl(_ownerDocument),
12-
DOMException: _globalObject.DOMException
13-
});
14-
}
15-
16-
exports.matchesDontThrow = (elImpl, selector) => {
17-
const document = elImpl._ownerDocument;
18-
19-
if (!document._nwsapiDontThrow) {
20-
document._nwsapiDontThrow = initNwsapi(elImpl);
21-
document._nwsapiDontThrow.configure({
22-
LOGERRORS: false,
23-
VERBOSITY: false,
24-
IDS_DUPES: true,
25-
MIXEDCASE: true
26-
});
7+
exports.matchesDontThrow = (selectors, elementImpl) => {
8+
let matched;
9+
try {
10+
const element = idlUtils.wrapperForImpl(elementImpl);
11+
matched = domSelector.matches(selectors, element);
12+
} catch {
13+
matched = false;
2714
}
15+
return matched;
16+
};
2817

29-
return document._nwsapiDontThrow.match(selector, idlUtils.wrapperForImpl(elImpl));
18+
exports.matches = (selectors, elementImpl, globalObject) => {
19+
let matched;
20+
try {
21+
const element = idlUtils.wrapperForImpl(elementImpl);
22+
matched = domSelector.matches(selectors, element);
23+
} catch (e) {
24+
if (e instanceof globalThis.DOMException &&
25+
!(e instanceof globalObject.DOMException)) {
26+
throw DOMException.create(globalObject, [e.message, e.name]);
27+
} else if (e instanceof globalThis.TypeError &&
28+
!(e instanceof globalObject.TypeError)) {
29+
throw new globalObject.TypeError(e.message);
30+
} else {
31+
throw e;
32+
}
33+
}
34+
return matched;
3035
};
3136

32-
// nwsapi gets `document.documentElement` at creation-time, so we have to initialize lazily, since in the initial
33-
// stages of Document initialization, there is no documentElement present yet.
34-
exports.addNwsapi = parentNode => {
35-
const document = parentNode._ownerDocument;
37+
exports.closest = (selectors, elementImpl, globalObject) => {
38+
let matched;
39+
try {
40+
const element = idlUtils.wrapperForImpl(elementImpl);
41+
matched = domSelector.closest(selectors, element);
42+
} catch (e) {
43+
if (e instanceof globalThis.DOMException &&
44+
!(e instanceof globalObject.DOMException)) {
45+
throw DOMException.create(globalObject, [e.message, e.name]);
46+
} else if (e instanceof globalThis.TypeError &&
47+
!(e instanceof globalObject.TypeError)) {
48+
throw new globalObject.TypeError(e.message);
49+
} else {
50+
throw e;
51+
}
52+
}
53+
return matched;
54+
};
3655

37-
if (!document._nwsapi) {
38-
document._nwsapi = initNwsapi(parentNode);
39-
document._nwsapi.configure({
40-
LOGERRORS: false,
41-
IDS_DUPES: true,
42-
MIXEDCASE: true
43-
});
56+
exports.querySelector = (selectors, parentNodeImpl, globalObject) => {
57+
let matched;
58+
try {
59+
const node = idlUtils.wrapperForImpl(parentNodeImpl);
60+
matched = domSelector.querySelector(selectors, node);
61+
} catch (e) {
62+
if (e instanceof globalThis.DOMException &&
63+
!(e instanceof globalObject.DOMException)) {
64+
throw DOMException.create(globalObject, [e.message, e.name]);
65+
} else if (e instanceof globalThis.TypeError &&
66+
!(e instanceof globalObject.TypeError)) {
67+
throw new globalObject.TypeError(e.message);
68+
} else {
69+
throw e;
70+
}
4471
}
72+
return matched;
73+
};
4574

46-
return document._nwsapi;
75+
exports.querySelectorAll = (selectors, parentNodeImpl, globalObject) => {
76+
let matched;
77+
try {
78+
const node = idlUtils.wrapperForImpl(parentNodeImpl);
79+
matched = domSelector.querySelectorAll(selectors, node);
80+
} catch (e) {
81+
if (e instanceof globalThis.DOMException &&
82+
!(e instanceof globalObject.DOMException)) {
83+
throw DOMException.create(globalObject, [e.message, e.name]);
84+
} else if (e instanceof globalThis.TypeError &&
85+
!(e instanceof globalObject.TypeError)) {
86+
throw new globalObject.TypeError(e.message);
87+
} else {
88+
throw e;
89+
}
90+
}
91+
return matched;
4792
};

lib/jsdom/living/helpers/style-rules.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,8 @@ exports.getDeclarationForElement = elementImpl => {
168168
return declaration;
169169
};
170170

171-
function matches(rule, element) {
172-
return matchesDontThrow(element, rule.selectorText);
171+
function matches(rule, elementImpl) {
172+
return matchesDontThrow(rule.selectorText, elementImpl);
173173
}
174174

175175
// Naive implementation of https://drafts.csswg.org/css-cascade-4/#cascading

lib/jsdom/living/nodes/Element-impl.js

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
"use strict";
2-
const { addNwsapi } = require("../helpers/selectors");
2+
const { closest, matches } = require("../helpers/selectors");
33
const { HTML_NS } = require("../helpers/namespaces");
44
const { mixin, memoizeQuery } = require("../../utils");
5-
const idlUtils = require("../generated/utils");
65
const NodeImpl = require("./Node-impl").implementation;
76
const ParentNodeImpl = require("./ParentNode-impl").implementation;
87
const ChildNodeImpl = require("./ChildNode-impl").implementation;
@@ -546,8 +545,15 @@ class ElementImpl extends NodeImpl {
546545
}
547546

548547
closest(selectors) {
549-
const matcher = addNwsapi(this);
550-
return matcher.closest(selectors, idlUtils.wrapperForImpl(this));
548+
return closest(selectors, this, this._globalObject);
549+
}
550+
551+
matches(selectors) {
552+
return matches(selectors, this, this._globalObject);
553+
}
554+
555+
webkitMatchesSelector(selectors) {
556+
return this.matches(selectors);
551557
}
552558

553559
// https://html.spec.whatwg.org/#reflecting-content-attributes-in-idl-attributes
@@ -586,14 +592,6 @@ ElementImpl.prototype.getElementsByClassName = memoizeQuery(function (classNames
586592
return listOfElementsWithClassNames(classNames, this);
587593
});
588594

589-
ElementImpl.prototype.matches = function (selectors) {
590-
const matcher = addNwsapi(this);
591-
592-
return matcher.match(selectors, idlUtils.wrapperForImpl(this));
593-
};
594-
595-
ElementImpl.prototype.webkitMatchesSelector = ElementImpl.prototype.matches;
596-
597595
module.exports = {
598596
implementation: ElementImpl
599597
};

lib/jsdom/living/nodes/ParentNode-impl.js

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
"use strict";
22

3-
const idlUtils = require("../generated/utils");
43
const NodeList = require("../generated/NodeList");
54
const HTMLCollection = require("../generated/HTMLCollection");
6-
const { addNwsapi } = require("../helpers/selectors");
5+
const { querySelector, querySelectorAll } = require("../helpers/selectors");
76
const { domSymbolTree } = require("../helpers/internal-constants");
87
const NODE_TYPE = require("../node-type");
98
const { convertNodesIntoNode } = require("../node");
@@ -62,30 +61,16 @@ class ParentNodeImpl {
6261
}
6362

6463
querySelector(selectors) {
65-
if (shouldAlwaysSelectNothing(this)) {
66-
return null;
67-
}
68-
const matcher = addNwsapi(this);
69-
return idlUtils.implForWrapper(matcher.first(selectors, idlUtils.wrapperForImpl(this)));
64+
return querySelector(selectors, this, this._globalObject);
7065
}
7166

7267
// Warning for internal users: this returns a NodeList containing IDL wrappers instead of impls
7368
querySelectorAll(selectors) {
74-
if (shouldAlwaysSelectNothing(this)) {
75-
return NodeList.create(this._globalObject, [], { nodes: [] });
76-
}
77-
const matcher = addNwsapi(this);
78-
const list = matcher.select(selectors, idlUtils.wrapperForImpl(this));
79-
80-
return NodeList.create(this._globalObject, [], { nodes: list.map(n => idlUtils.tryImplForWrapper(n)) });
69+
const nodes = querySelectorAll(selectors, this, this._globalObject);
70+
return NodeList.create(this._globalObject, [], { nodes });
8171
}
8272
}
8373

84-
function shouldAlwaysSelectNothing(elImpl) {
85-
// This is true during initialization.
86-
return elImpl === elImpl._ownerDocument && !elImpl.documentElement;
87-
}
88-
8974
module.exports = {
9075
implementation: ParentNodeImpl
9176
};

package-lock.json

Lines changed: 53 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"license": "MIT",
2121
"repository": "jsdom/jsdom",
2222
"dependencies": {
23+
"@asamuzakjp/dom-selector": "^1.2.5",
2324
"cssstyle": "^4.0.1",
2425
"data-urls": "^5.0.0",
2526
"decimal.js": "^10.4.3",
@@ -28,7 +29,6 @@
2829
"http-proxy-agent": "^7.0.0",
2930
"https-proxy-agent": "^7.0.2",
3031
"is-potential-custom-element-name": "^1.0.1",
31-
"nwsapi": "^2.2.7",
3232
"parse5": "^7.1.2",
3333
"rrweb-cssom": "^0.6.0",
3434
"saxes": "^6.0.0",

0 commit comments

Comments
 (0)