From 1d965f96d8489b62f2206d50dc6d2830e74e19d4 Mon Sep 17 00:00:00 2001 From: David Ortner Date: Fri, 15 Sep 2023 21:36:40 +0200 Subject: [PATCH] #1069@trivial: Fixes __dirname not defined error when using ESM. --- .github/workflows/release.yml | 6 ++-- package-lock.json | 18 ++++-------- packages/happy-dom/bin/build-version-file.cjs | 20 +++++++++++++ .../happy-dom/bin/change-file-extension.cjs | 13 +++++---- packages/happy-dom/package.json | 3 +- .../src/navigator/NavigatorUtility.ts | 29 ------------------- .../HTMLUnknownElement.ts | 2 +- packages/happy-dom/src/version.ts | 1 + packages/happy-dom/src/window/Window.ts | 6 ++-- .../HTMLUnknownElement.test.ts | 16 +++++++++- packages/happy-dom/test/window/Window.test.ts | 22 +++++++------- 11 files changed, 70 insertions(+), 66 deletions(-) create mode 100644 packages/happy-dom/bin/build-version-file.cjs delete mode 100644 packages/happy-dom/src/navigator/NavigatorUtility.ts create mode 100644 packages/happy-dom/src/version.ts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3b868addb..ff6e5224d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -89,15 +89,15 @@ jobs: run: | npm ci --ignore-scripts + - name: Set version + run: node ./bin/set-version.js --version=${{needs.check-next-version.outputs.next_version }} + - name: Compile packages run: npm run compile - name: Run tests run: npm run test - - name: Set version - run: node ./bin/set-version.js --version=${{needs.check-next-version.outputs.next_version }} - - name: Configures Git run: | git config --global user.name "${{ github.actor }}" diff --git a/package-lock.json b/package-lock.json index 985ef6684..010c91e24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12828,8 +12828,7 @@ "version": "14.4.3", "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.4.3.tgz", "integrity": "sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==", - "dev": true, - "requires": {} + "dev": true }, "@types/aria-query": { "version": "5.0.1", @@ -13483,8 +13482,7 @@ "version": "6.6.2", "resolved": "https://registry.npmjs.org/@webref/css/-/css-6.6.2.tgz", "integrity": "sha512-BtX/sMtWl6eJfspxTQfmINpSEP/BvwQz1OL1FEiPffRDRZVEP9s4Nf/pyf16o9j/1SEj1LmevUCHABzSsktDvQ==", - "dev": true, - "requires": {} + "dev": true }, "accepts": { "version": "1.3.8", @@ -13506,8 +13504,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} + "dev": true }, "acorn-walk": { "version": "8.2.0", @@ -14971,8 +14968,7 @@ "version": "8.5.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true, - "requires": {} + "dev": true }, "eslint-import-resolver-node": { "version": "0.3.7", @@ -15125,8 +15121,7 @@ "version": "0.0.7", "resolved": "https://registry.npmjs.org/eslint-plugin-turbo/-/eslint-plugin-turbo-0.0.7.tgz", "integrity": "sha512-iajOH8eD4jha3duztGVBD1BEmvNrQBaA/y3HFHf91vMDRYRwH7BpHSDFtxydDpk5ghlhRxG299SFxz7D6z4MBQ==", - "dev": true, - "requires": {} + "dev": true }, "eslint-scope": { "version": "5.1.1", @@ -17056,8 +17051,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "requires": {} + "dev": true }, "jest-regex-util": { "version": "29.4.3", diff --git a/packages/happy-dom/bin/build-version-file.cjs b/packages/happy-dom/bin/build-version-file.cjs new file mode 100644 index 000000000..8fe8af20e --- /dev/null +++ b/packages/happy-dom/bin/build-version-file.cjs @@ -0,0 +1,20 @@ +/* eslint-disable no-console*/ + +const Path = require('path'); +const FS = require('fs'); +const packageJson = require('../package.json'); + +async function main() { + await Promise.all([ + FS.promises.writeFile( + Path.resolve(Path.join('.', 'lib', 'version.js')), + `export default { version: '${packageJson.version}' };` + ), + FS.promises.writeFile( + Path.resolve(Path.join('.', 'cjs', 'version.cjs')), + `module.exports = { default: { version: '${packageJson.version}' } };` + ) + ]); +} + +main(); diff --git a/packages/happy-dom/bin/change-file-extension.cjs b/packages/happy-dom/bin/change-file-extension.cjs index 039a07e9c..7d718cf79 100644 --- a/packages/happy-dom/bin/change-file-extension.cjs +++ b/packages/happy-dom/bin/change-file-extension.cjs @@ -55,9 +55,13 @@ async function readDirectory(directory) { } async function renameFiles(files, args) { + const fromExtEscaped = args.fromExt.replace('.', '\\.'); const newFiles = files.map((file) => ({ oldPath: file, - newPath: file.replace(args.fromExt, args.toExt) + newPath: file.replace( + new RegExp(`${fromExtEscaped}$|${fromExtEscaped}(\\.)`), + `${args.toExt}$1` + ) })); const writePromises = []; @@ -66,11 +70,8 @@ async function renameFiles(files, args) { FS.promises.readFile(file.oldPath).then((content) => { const oldContent = content.toString(); const newContent = oldContent - .replace( - new RegExp(`${args.fromExt.replace('.', '\\.')}\\.map`, 'g'), - `${args.toExt}.map` - ) - .replace(new RegExp(`${args.fromExt.replace('.', '\\.')}(["'])`, 'g'), `${args.toExt}$1`); + .replace(new RegExp(`${fromExtEscaped}\\.map`, 'g'), `${args.toExt}.map`) + .replace(new RegExp(`${fromExtEscaped}(["'])`, 'g'), `${args.toExt}$1`); return FS.promises.writeFile(file.newPath, newContent).then(() => { if (file.oldPath !== file.newPath) { return FS.promises.unlink(file.oldPath); diff --git a/packages/happy-dom/package.json b/packages/happy-dom/package.json index c413c9d3c..39b503f58 100644 --- a/packages/happy-dom/package.json +++ b/packages/happy-dom/package.json @@ -65,8 +65,9 @@ "access": "public" }, "scripts": { - "compile": "tsc && tsc --module CommonJS --outDir cjs && npm run change-cjs-file-extension", + "compile": "tsc && tsc --module CommonJS --outDir cjs && npm run change-cjs-file-extension && npm run build-version-file", "change-cjs-file-extension": "node ./bin/change-file-extension.cjs --dir=./cjs --fromExt=.js --toExt=.cjs", + "build-version-file": "node ./bin/build-version-file.cjs", "watch": "tsc -w --preserveWatchOutput", "lint": "eslint --ignore-path .gitignore --max-warnings 0 .", "lint:fix": "eslint --ignore-path .gitignore --max-warnings 0 --fix .", diff --git a/packages/happy-dom/src/navigator/NavigatorUtility.ts b/packages/happy-dom/src/navigator/NavigatorUtility.ts deleted file mode 100644 index d2e1052b2..000000000 --- a/packages/happy-dom/src/navigator/NavigatorUtility.ts +++ /dev/null @@ -1,29 +0,0 @@ -import FS from 'fs'; -import Path from 'path'; - -/** - * Utility for navigator. - */ -export default class NavigatorUtility { - /** - * Returns the package version. - * - * @returns Package version. - */ - public static getHappyDOMVersion(): string { - const content = FS.readFileSync(Path.join(__dirname, '..', '..', 'package.json')).toString(); - const json = JSON.parse(content); - return json.version; - } - - /** - * Returns platform. - * - * @returns Platform. - */ - public static getPlatform(): string { - const platform = process.platform; - const platformCapitalized = platform.charAt(0).toUpperCase() + platform.slice(1); - return 'X11; ' + platformCapitalized + ' ' + process.arch; - } -} diff --git a/packages/happy-dom/src/nodes/html-unknown-element/HTMLUnknownElement.ts b/packages/happy-dom/src/nodes/html-unknown-element/HTMLUnknownElement.ts index a921c0210..d641fbcb7 100644 --- a/packages/happy-dom/src/nodes/html-unknown-element/HTMLUnknownElement.ts +++ b/packages/happy-dom/src/nodes/html-unknown-element/HTMLUnknownElement.ts @@ -27,7 +27,7 @@ export default class HTMLUnknownElement extends HTMLElement implements IHTMLElem // This element can potentially be a custom element that has not been defined yet // Therefore we need to register a callback for when it is defined in CustomElementRegistry and replace it with the registered element (see #404) - if (tagName.includes('-')) { + if (tagName.includes('-') && this.ownerDocument.defaultView.customElements._callbacks) { const callbacks = this.ownerDocument.defaultView.customElements._callbacks; if (parentNode && !this._customElementDefineCallback) { diff --git a/packages/happy-dom/src/version.ts b/packages/happy-dom/src/version.ts new file mode 100644 index 000000000..e077dc237 --- /dev/null +++ b/packages/happy-dom/src/version.ts @@ -0,0 +1 @@ +export default { version: '0.0.0' }; diff --git a/packages/happy-dom/src/window/Window.ts b/packages/happy-dom/src/window/Window.ts index eb2093c02..93ea64236 100644 --- a/packages/happy-dom/src/window/Window.ts +++ b/packages/happy-dom/src/window/Window.ts @@ -140,7 +140,7 @@ import WindowErrorUtility from './WindowErrorUtility.js'; import VirtualConsole from '../console/VirtualConsole.js'; import VirtualConsolePrinter from '../console/VirtualConsolePrinter.js'; import IHappyDOMSettings from './IHappyDOMSettings.js'; -import NavigatorUtility from '../navigator/NavigatorUtility.js'; +import PackageVersion from '../version.js'; const ORIGINAL_SET_TIMEOUT = setTimeout; const ORIGINAL_CLEAR_TIMEOUT = clearTimeout; @@ -212,7 +212,9 @@ export default class Window extends EventTarget implements IWindow { disableComputedStyleRendering: false, enableFileSystemHttpRequests: false, navigator: { - userAgent: `Mozilla/5.0 (${NavigatorUtility.getPlatform()}) AppleWebKit/537.36 (KHTML, like Gecko) HappyDOM/${NavigatorUtility.getHappyDOMVersion()}` + userAgent: `Mozilla/5.0 (X11; ${ + process.platform.charAt(0).toUpperCase() + process.platform.slice(1) + ' ' + process.arch + }) AppleWebKit/537.36 (KHTML, like Gecko) HappyDOM/${PackageVersion.version}` }, device: { prefersColorScheme: 'light', diff --git a/packages/happy-dom/test/nodes/html-unknown-element/HTMLUnknownElement.test.ts b/packages/happy-dom/test/nodes/html-unknown-element/HTMLUnknownElement.test.ts index 9ccde278c..a5f002db2 100644 --- a/packages/happy-dom/test/nodes/html-unknown-element/HTMLUnknownElement.test.ts +++ b/packages/happy-dom/test/nodes/html-unknown-element/HTMLUnknownElement.test.ts @@ -4,6 +4,7 @@ import IDocument from '../../../src/nodes/document/IDocument.js'; import HTMLUnknownElement from '../../../src/nodes/html-unknown-element/HTMLUnknownElement.js'; import CustomElement from '../../CustomElement.js'; import { beforeEach, describe, it, expect } from 'vitest'; +import CustomElementRegistry from '../../../src/custom-element/CustomElementRegistry.js'; describe('HTMLUnknownElement', () => { let window: IWindow; @@ -72,7 +73,7 @@ describe('HTMLUnknownElement', () => { expect(customElement instanceof CustomElement).toBe(true); expect(customElement.isConnected).toBe(true); - expect(customElement.shadowRoot.children.length).toBe(2); + expect(customElement.shadowRoot?.children.length).toBe(2); expect(customElement.childNodes === childNodes).toBe(true); expect(customElement.children === children).toBe(true); @@ -85,5 +86,18 @@ describe('HTMLUnknownElement', () => { expect(customElement.attributes.length).toBe(1); expect(customElement.attributes[0] === attribute1).toBe(true); }); + + it('Does nothing if the property "_callback" doesn\'t exist on Window.customElements.', () => { + (window.customElements) = ({ + get: () => undefined + }); + + const element = document.createElement('custom-element'); + const parent = document.createElement('div'); + + expect(() => { + parent.appendChild(element); + }).not.toThrow(); + }); }); }); diff --git a/packages/happy-dom/test/window/Window.test.ts b/packages/happy-dom/test/window/Window.test.ts index 916f51994..c5d80563e 100644 --- a/packages/happy-dom/test/window/Window.test.ts +++ b/packages/happy-dom/test/window/Window.test.ts @@ -26,14 +26,16 @@ import '../types.d.js'; import { beforeEach, afterEach, describe, it, expect, vi } from 'vitest'; import VirtualConsole from '../../src/console/VirtualConsole.js'; import VirtualConsolePrinter from '../../src/console/VirtualConsolePrinter.js'; -import NavigatorUtility from '../../src/navigator/NavigatorUtility.js'; -import PackageJson from '../../package.json'; +import PackageVersion from '../../src/version.js'; const GET_NAVIGATOR_PLATFORM = (): string => { - const processPlatform = process.platform; - const processPlatformCapitalized = - processPlatform.charAt(0).toUpperCase() + processPlatform.slice(1); - return 'X11; ' + processPlatformCapitalized + ' ' + process.arch; + return ( + 'X11; ' + + process.platform.charAt(0).toUpperCase() + + process.platform.slice(1) + + ' ' + + process.arch + ); }; describe('Window', () => { @@ -151,7 +153,7 @@ describe('Window', () => { expect(windowWithoutOptions.happyDOM.settings.enableFileSystemHttpRequests).toBe(false); expect(windowWithoutOptions.happyDOM.settings.navigator.userAgent).toBe( `Mozilla/5.0 (${GET_NAVIGATOR_PLATFORM()}) AppleWebKit/537.36 (KHTML, like Gecko) HappyDOM/${ - PackageJson.version + PackageVersion.version }` ); expect(windowWithoutOptions.happyDOM.settings.device.prefersColorScheme).toBe('light'); @@ -457,9 +459,7 @@ describe('Window', () => { const referenceValues = { appCodeName: 'Mozilla', appName: 'Netscape', - appVersion: `5.0 (${NavigatorUtility.getPlatform()}) AppleWebKit/537.36 (KHTML, like Gecko) HappyDOM/${ - PackageJson.version - }`, + appVersion: `5.0 (${platform}) AppleWebKit/537.36 (KHTML, like Gecko) HappyDOM/${PackageVersion.version}`, cookieEnabled: true, credentials: null, doNotTrack: 'unspecified', @@ -480,7 +480,7 @@ describe('Window', () => { }, product: 'Gecko', productSub: '20100101', - userAgent: `Mozilla/5.0 (${platform}) AppleWebKit/537.36 (KHTML, like Gecko) HappyDOM/${PackageJson.version}`, + userAgent: `Mozilla/5.0 (${platform}) AppleWebKit/537.36 (KHTML, like Gecko) HappyDOM/${PackageVersion.version}`, vendor: '', vendorSub: '', webdriver: true