diff --git a/dev/patch-dependencies.js b/dev/patch-dependencies.js
new file mode 100644
index 00000000..8f4ffb76
--- /dev/null
+++ b/dev/patch-dependencies.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 Yomichan Authors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+const fs = require('fs');
+const assert = require('assert');
+
+/**
+ * This function patches the following bug:
+ * * https://github.com/jsdom/jsdom/issues/3211
+ * * https://github.com/dperini/nwsapi/issues/48
+ */
+function patchNwsapi() {
+ const nwsapiPath = require.resolve('nwsapi');
+ const nwsapiSource = fs.readFileSync(nwsapiPath, {encoding: 'utf8'});
+ const pattern = /(if|while)(\()(?:e&&)?(\(e=e\.parentElement\)\)\{)/g;
+ let modifications = 0;
+ const nwsapiSourceNew = nwsapiSource.replace(pattern, (g0, g1, g2, g3) => {
+ ++modifications;
+ return `${g1}${g2}e&&${g3}`;
+ });
+ assert.strictEqual(modifications, 2);
+ fs.writeFileSync(nwsapiPath, nwsapiSourceNew, {encoding: 'utf8'});
+ // nwsapi is used by JSDOM
+ const {testJSDOM} = require('../test/test-jsdom');
+ testJSDOM();
+}
+
+function main() {
+ patchNwsapi();
+}
+
+if (require.main === module) { main(); }
diff --git a/package.json b/package.json
index 872f7dbb..ee30ea60 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,7 @@
"test": "test"
},
"scripts": {
+ "postinstall": "node ./dev/patch-dependencies.js",
"build": "node ./dev/build.js",
"test": "npm run test-lint && npm run test-lint-css && npm run test-lint-html && npm run test-code && npm run test-manifest && npm run test-build",
"test-lint": "npx eslint . && node ./dev/lint/global-declarations.js && node ./dev/lint/html-scripts.js",
diff --git a/test/test-jsdom.js b/test/test-jsdom.js
new file mode 100644
index 00000000..8b00127d
--- /dev/null
+++ b/test/test-jsdom.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 Yomichan Authors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+const assert = require('assert');
+const {testMain} = require('../dev/util');
+
+/**
+ * This function tests the following bug:
+ * * https://github.com/jsdom/jsdom/issues/3211
+ * * https://github.com/dperini/nwsapi/issues/48
+ */
+function testJSDOMSelectorBug() {
+ // nwsapi is used by JSDOM
+ const {JSDOM} = require('jsdom');
+ const dom = new JSDOM();
+ const {document} = dom.window;
+ const div = document.createElement('div');
+ div.innerHTML = '
';
+ const c = div.querySelector('.c');
+ assert.doesNotThrow(() => { c.matches('.a:nth-last-of-type(1) .b .c'); });
+}
+
+function testJSDOM() {
+ testJSDOMSelectorBug();
+}
+
+function main() {
+ testJSDOM();
+}
+
+module.exports = {
+ testJSDOM
+};
+
+if (require.main === module) { testMain(main); }