From 5922b33918fe3638c98cd33b89bf96e3417ae8ad Mon Sep 17 00:00:00 2001 From: David Ortner Date: Fri, 22 Sep 2023 13:31:55 +0200 Subject: [PATCH 1/2] #847@patch: Fixes bug in URL.createObjectURL() where it did not support the Happy DOM Blob object. --- packages/happy-dom/src/cookie/Cookie.ts | 2 +- packages/happy-dom/src/cookie/CookieJar.ts | 2 +- packages/happy-dom/src/fetch/Fetch.ts | 2 +- packages/happy-dom/src/fetch/Request.ts | 2 +- packages/happy-dom/src/fetch/ResourceFetch.ts | 2 +- packages/happy-dom/src/fetch/Response.ts | 3 ++- .../happy-dom/src/fetch/types/IRequestInfo.ts | 2 +- .../happy-dom/src/fetch/types/IRequestInit.ts | 2 +- .../utilities/FetchRequestReferrerUtility.ts | 2 +- .../FetchRequestValidationUtility.ts | 2 +- packages/happy-dom/src/index.ts | 3 ++- packages/happy-dom/src/location/Location.ts | 2 +- .../html-anchor-element/HTMLAnchorElement.ts | 2 +- .../HTMLAnchorElementUtility.ts | 2 +- .../html-iframe-element/HTMLIFrameUtility.ts | 2 +- packages/happy-dom/src/url/URL.ts | 22 +++++++++++++++++++ packages/happy-dom/src/window/IWindow.ts | 3 ++- packages/happy-dom/src/window/Window.ts | 3 ++- .../src/xml-http-request/XMLHttpRequest.ts | 3 ++- .../utilities/XMLHttpRequestURLUtility.ts | 3 ++- .../happy-dom/test/cookie/CookieJar.test.ts | 2 +- packages/happy-dom/test/fetch/Request.test.ts | 2 +- packages/happy-dom/test/url/URL.test.ts | 18 +++++++++++++++ 23 files changed, 67 insertions(+), 21 deletions(-) create mode 100644 packages/happy-dom/src/url/URL.ts create mode 100644 packages/happy-dom/test/url/URL.test.ts diff --git a/packages/happy-dom/src/cookie/Cookie.ts b/packages/happy-dom/src/cookie/Cookie.ts index 137075f61..c06d5b23c 100644 --- a/packages/happy-dom/src/cookie/Cookie.ts +++ b/packages/happy-dom/src/cookie/Cookie.ts @@ -1,7 +1,7 @@ import DOMException from '../exception/DOMException.js'; import DOMExceptionNameEnum from '../exception/DOMExceptionNameEnum.js'; import CookieSameSiteEnum from './CookieSameSiteEnum.js'; -import { URL } from 'url'; +import URL from '../url/URL.js'; /** * Cookie. diff --git a/packages/happy-dom/src/cookie/CookieJar.ts b/packages/happy-dom/src/cookie/CookieJar.ts index 606be3376..389e93d41 100644 --- a/packages/happy-dom/src/cookie/CookieJar.ts +++ b/packages/happy-dom/src/cookie/CookieJar.ts @@ -1,6 +1,6 @@ import Cookie from './Cookie.js'; import CookieSameSiteEnum from './CookieSameSiteEnum.js'; -import { URL } from 'url'; +import URL from '../url/URL.js'; /** * CookieJar. diff --git a/packages/happy-dom/src/fetch/Fetch.ts b/packages/happy-dom/src/fetch/Fetch.ts index dd11e8849..4223131c0 100644 --- a/packages/happy-dom/src/fetch/Fetch.ts +++ b/packages/happy-dom/src/fetch/Fetch.ts @@ -11,7 +11,7 @@ import Response from './Response.js'; import HTTP, { IncomingMessage } from 'http'; import HTTPS from 'https'; import Zlib from 'zlib'; -import { URL } from 'url'; +import URL from '../url/URL.js'; import { Socket } from 'net'; import Stream from 'stream'; import DataURIParser from './data-uri/DataURIParser.js'; diff --git a/packages/happy-dom/src/fetch/Request.ts b/packages/happy-dom/src/fetch/Request.ts index cfe241ca3..fbefbe0b2 100644 --- a/packages/happy-dom/src/fetch/Request.ts +++ b/packages/happy-dom/src/fetch/Request.ts @@ -1,7 +1,7 @@ import IBlob from '../file/IBlob.js'; import IDocument from '../nodes/document/IDocument.js'; import IRequestInit from './types/IRequestInit.js'; -import { URL } from 'url'; +import URL from '../url/URL.js'; import DOMException from '../exception/DOMException.js'; import DOMExceptionNameEnum from '../exception/DOMExceptionNameEnum.js'; import IRequestInfo from './types/IRequestInfo.js'; diff --git a/packages/happy-dom/src/fetch/ResourceFetch.ts b/packages/happy-dom/src/fetch/ResourceFetch.ts index 9e1034827..7621d94a6 100644 --- a/packages/happy-dom/src/fetch/ResourceFetch.ts +++ b/packages/happy-dom/src/fetch/ResourceFetch.ts @@ -1,6 +1,6 @@ import DOMException from '../exception/DOMException.js'; import IDocument from '../nodes/document/IDocument.js'; -import { URL } from 'url'; +import URL from '../url/URL.js'; /** * Helper class for performing fetch of resources. diff --git a/packages/happy-dom/src/fetch/Response.ts b/packages/happy-dom/src/fetch/Response.ts index c35d38fb4..72b19d2ae 100644 --- a/packages/happy-dom/src/fetch/Response.ts +++ b/packages/happy-dom/src/fetch/Response.ts @@ -5,7 +5,8 @@ import IResponseInit from './types/IResponseInit.js'; import IResponseBody from './types/IResponseBody.js'; import Headers from './Headers.js'; import IHeaders from './types/IHeaders.js'; -import { URL, URLSearchParams } from 'url'; +import { URLSearchParams } from 'url'; +import URL from '../url/URL.js'; import Blob from '../file/Blob.js'; import Stream from 'stream'; import FormData from '../form-data/FormData.js'; diff --git a/packages/happy-dom/src/fetch/types/IRequestInfo.ts b/packages/happy-dom/src/fetch/types/IRequestInfo.ts index 65a55dd88..6b2bb16eb 100644 --- a/packages/happy-dom/src/fetch/types/IRequestInfo.ts +++ b/packages/happy-dom/src/fetch/types/IRequestInfo.ts @@ -1,4 +1,4 @@ -import { URL } from 'url'; +import URL from '../../url/URL.js'; import IRequest from './IRequest.js'; type IRequestInfo = IRequest | string | URL; diff --git a/packages/happy-dom/src/fetch/types/IRequestInit.ts b/packages/happy-dom/src/fetch/types/IRequestInit.ts index 5d55cd519..4c6e1a8b1 100644 --- a/packages/happy-dom/src/fetch/types/IRequestInit.ts +++ b/packages/happy-dom/src/fetch/types/IRequestInit.ts @@ -1,6 +1,6 @@ import IHeadersInit from './IHeadersInit.js'; import AbortSignal from '../AbortSignal.js'; -import { URL } from 'url'; +import URL from '../../url/URL.js'; import IRequestReferrerPolicy from './IRequestReferrerPolicy.js'; import IRequestRedirect from './IRequestRedirect.js'; import IRequestBody from './IRequestBody.js'; diff --git a/packages/happy-dom/src/fetch/utilities/FetchRequestReferrerUtility.ts b/packages/happy-dom/src/fetch/utilities/FetchRequestReferrerUtility.ts index f352352a7..8de395d1e 100644 --- a/packages/happy-dom/src/fetch/utilities/FetchRequestReferrerUtility.ts +++ b/packages/happy-dom/src/fetch/utilities/FetchRequestReferrerUtility.ts @@ -1,4 +1,4 @@ -import { URL } from 'url'; +import URL from '../../url/URL.js'; import IRequest from '../types/IRequest.js'; import IDocument from '../../nodes/document/IDocument.js'; import { isIP } from 'net'; diff --git a/packages/happy-dom/src/fetch/utilities/FetchRequestValidationUtility.ts b/packages/happy-dom/src/fetch/utilities/FetchRequestValidationUtility.ts index c7ee5daa0..a51d33b27 100644 --- a/packages/happy-dom/src/fetch/utilities/FetchRequestValidationUtility.ts +++ b/packages/happy-dom/src/fetch/utilities/FetchRequestValidationUtility.ts @@ -2,7 +2,7 @@ import DOMException from '../../exception/DOMException.js'; import DOMExceptionNameEnum from '../../exception/DOMExceptionNameEnum.js'; import IRequestReferrerPolicy from '../types/IRequestReferrerPolicy.js'; import IRequestRedirect from '../types/IRequestRedirect.js'; -import { URL } from 'url'; +import URL from '../../url/URL.js'; import IRequest from '../types/IRequest.js'; const VALID_REFERRER_POLICIES = [ diff --git a/packages/happy-dom/src/index.ts b/packages/happy-dom/src/index.ts index 8d929a04b..53661339c 100644 --- a/packages/happy-dom/src/index.ts +++ b/packages/happy-dom/src/index.ts @@ -4,7 +4,8 @@ import Window from './window/Window.js'; import DataTransfer from './event/DataTransfer.js'; import DataTransferItem from './event/DataTransferItem.js'; import DataTransferItemList from './event/DataTransferItemList.js'; -import { URL, URLSearchParams } from 'url'; +import { URLSearchParams } from 'url'; +import URL from './url/URL.js'; import Location from './location/Location.js'; import MutationObserver from './mutation-observer/MutationObserver.js'; import ResizeObserver from './resize-observer/ResizeObserver.js'; diff --git a/packages/happy-dom/src/location/Location.ts b/packages/happy-dom/src/location/Location.ts index 2d38db695..f32e47d46 100644 --- a/packages/happy-dom/src/location/Location.ts +++ b/packages/happy-dom/src/location/Location.ts @@ -1,4 +1,4 @@ -import { URL } from 'url'; +import URL from '../url/URL.js'; import DOMException from '../exception/DOMException.js'; import DOMExceptionNameEnum from '../exception/DOMExceptionNameEnum.js'; diff --git a/packages/happy-dom/src/nodes/html-anchor-element/HTMLAnchorElement.ts b/packages/happy-dom/src/nodes/html-anchor-element/HTMLAnchorElement.ts index d4c42968a..e68d81f98 100644 --- a/packages/happy-dom/src/nodes/html-anchor-element/HTMLAnchorElement.ts +++ b/packages/happy-dom/src/nodes/html-anchor-element/HTMLAnchorElement.ts @@ -2,7 +2,7 @@ import HTMLElement from '../html-element/HTMLElement.js'; import DOMTokenList from '../../dom-token-list/DOMTokenList.js'; import IDOMTokenList from '../../dom-token-list/IDOMTokenList.js'; import IHTMLAnchorElement from './IHTMLAnchorElement.js'; -import { URL } from 'url'; +import URL from '../../url/URL.js'; import HTMLAnchorElementUtility from './HTMLAnchorElementUtility.js'; import INamedNodeMap from '../../named-node-map/INamedNodeMap.js'; import HTMLAnchorElementNamedNodeMap from './HTMLAnchorElementNamedNodeMap.js'; diff --git a/packages/happy-dom/src/nodes/html-anchor-element/HTMLAnchorElementUtility.ts b/packages/happy-dom/src/nodes/html-anchor-element/HTMLAnchorElementUtility.ts index a0ae8e4ce..bcdbaa59e 100644 --- a/packages/happy-dom/src/nodes/html-anchor-element/HTMLAnchorElementUtility.ts +++ b/packages/happy-dom/src/nodes/html-anchor-element/HTMLAnchorElementUtility.ts @@ -1,5 +1,5 @@ import IDocument from '../document/IDocument.js'; -import { URL } from 'url'; +import URL from '../../url/URL.js'; /** * HTML Anchor Element utility. diff --git a/packages/happy-dom/src/nodes/html-iframe-element/HTMLIFrameUtility.ts b/packages/happy-dom/src/nodes/html-iframe-element/HTMLIFrameUtility.ts index 2a430b6da..25accebf4 100644 --- a/packages/happy-dom/src/nodes/html-iframe-element/HTMLIFrameUtility.ts +++ b/packages/happy-dom/src/nodes/html-iframe-element/HTMLIFrameUtility.ts @@ -1,4 +1,4 @@ -import { URL } from 'url'; +import URL from '../../url/URL.js'; import Event from '../../event/Event.js'; import ErrorEvent from '../../event/events/ErrorEvent.js'; import IWindow from '../../window/IWindow.js'; diff --git a/packages/happy-dom/src/url/URL.ts b/packages/happy-dom/src/url/URL.ts new file mode 100644 index 000000000..39ffae780 --- /dev/null +++ b/packages/happy-dom/src/url/URL.ts @@ -0,0 +1,22 @@ +import { URL as NodeJSURL } from 'url'; +import { Blob as NodeJSBlob } from 'buffer'; +import Blob from '../file/Blob.js'; + +/** + * URL. + */ +export default class URL extends NodeJSURL { + /** + * Creates a string containing a URL representing the object given in the parameter. + * + * @param object Object. + * @returns URL. + */ + public static override createObjectURL(object: NodeJSBlob | Blob): string { + if (object instanceof Blob) { + const blob = new NodeJSBlob([object._buffer], { type: object.type }); + return super.createObjectURL(blob); + } + return super.createObjectURL(object); + } +} diff --git a/packages/happy-dom/src/window/IWindow.ts b/packages/happy-dom/src/window/IWindow.ts index eb786e0e3..716c96ebf 100644 --- a/packages/happy-dom/src/window/IWindow.ts +++ b/packages/happy-dom/src/window/IWindow.ts @@ -42,7 +42,8 @@ import KeyboardEvent from '../event/events/KeyboardEvent.js'; import ProgressEvent from '../event/events/ProgressEvent.js'; import MediaQueryListEvent from '../event/events/MediaQueryListEvent.js'; import EventTarget from '../event/EventTarget.js'; -import { URL, URLSearchParams } from 'url'; +import { URLSearchParams } from 'url'; +import URL from '../url/URL.js'; import Location from '../location/Location.js'; import MutationObserver from '../mutation-observer/MutationObserver.js'; import DOMParser from '../dom-parser/DOMParser.js'; diff --git a/packages/happy-dom/src/window/Window.ts b/packages/happy-dom/src/window/Window.ts index 67562cb04..b5aa45b12 100644 --- a/packages/happy-dom/src/window/Window.ts +++ b/packages/happy-dom/src/window/Window.ts @@ -47,7 +47,8 @@ import ProgressEvent from '../event/events/ProgressEvent.js'; import MediaQueryListEvent from '../event/events/MediaQueryListEvent.js'; import EventTarget from '../event/EventTarget.js'; import MessagePort from '../event/MessagePort.js'; -import { URL, URLSearchParams } from 'url'; +import { URLSearchParams } from 'url'; +import URL from '../url/URL.js'; import Location from '../location/Location.js'; import NonImplementedEventTypes from '../event/NonImplementedEventTypes.js'; import MutationObserver from '../mutation-observer/MutationObserver.js'; diff --git a/packages/happy-dom/src/xml-http-request/XMLHttpRequest.ts b/packages/happy-dom/src/xml-http-request/XMLHttpRequest.ts index 045cec529..c3685e7f0 100644 --- a/packages/happy-dom/src/xml-http-request/XMLHttpRequest.ts +++ b/packages/happy-dom/src/xml-http-request/XMLHttpRequest.ts @@ -10,7 +10,8 @@ import Blob from '../file/Blob.js'; import XMLHttpRequestUpload from './XMLHttpRequestUpload.js'; import DOMException from '../exception/DOMException.js'; import DOMExceptionNameEnum from '../exception/DOMExceptionNameEnum.js'; -import { URL, UrlObject } from 'url'; +import { UrlObject } from 'url'; +import URL from '../url/URL.js'; import XMLHttpRequestURLUtility from './utilities/XMLHttpRequestURLUtility.js'; import ProgressEvent from '../event/events/ProgressEvent.js'; import XMLHttpResponseTypeEnum from './XMLHttpResponseTypeEnum.js'; diff --git a/packages/happy-dom/src/xml-http-request/utilities/XMLHttpRequestURLUtility.ts b/packages/happy-dom/src/xml-http-request/utilities/XMLHttpRequestURLUtility.ts index a75e30db8..c971ebb5f 100644 --- a/packages/happy-dom/src/xml-http-request/utilities/XMLHttpRequestURLUtility.ts +++ b/packages/happy-dom/src/xml-http-request/utilities/XMLHttpRequestURLUtility.ts @@ -1,4 +1,5 @@ -import { URL, UrlObject } from 'url'; +import { UrlObject } from 'url'; +import URL from '../../url/URL.js'; import Path from 'path'; // MIME type. diff --git a/packages/happy-dom/test/cookie/CookieJar.test.ts b/packages/happy-dom/test/cookie/CookieJar.test.ts index 2675d3a80..e00a7502e 100644 --- a/packages/happy-dom/test/cookie/CookieJar.test.ts +++ b/packages/happy-dom/test/cookie/CookieJar.test.ts @@ -1,5 +1,5 @@ import CookieJar from '../../src/cookie/CookieJar.js'; -import { URL } from 'url'; +import URL from '../../src/url/URL.js'; import { beforeEach, afterEach, describe, it, expect, vi } from 'vitest'; describe('CookieJar', () => { diff --git a/packages/happy-dom/test/fetch/Request.test.ts b/packages/happy-dom/test/fetch/Request.test.ts index b75c4f9ad..d94d96dad 100644 --- a/packages/happy-dom/test/fetch/Request.test.ts +++ b/packages/happy-dom/test/fetch/Request.test.ts @@ -2,7 +2,7 @@ import IWindow from '../../src/window/IWindow.js'; import Window from '../../src/window/Window.js'; import IDocument from '../../src/nodes/document/IDocument.js'; import Request from '../../src/fetch/Request.js'; -import { URL } from 'url'; +import URL from '../../src/url/URL.js'; import Headers from '../../src/fetch/Headers.js'; import AbortSignal from '../../src/fetch/AbortSignal.js'; import DOMException from '../../src/exception/DOMException.js'; diff --git a/packages/happy-dom/test/url/URL.test.ts b/packages/happy-dom/test/url/URL.test.ts new file mode 100644 index 000000000..196b5daa8 --- /dev/null +++ b/packages/happy-dom/test/url/URL.test.ts @@ -0,0 +1,18 @@ +import URL from '../../src/url/URL.js'; +import Blob from '../../src/file/Blob.js'; +import { Blob as NodeJSBlob } from 'buffer'; +import { describe, it, expect } from 'vitest'; + +describe('URL', () => { + describe('createObjectURL()', () => { + it('Creates a string containing a URL representing the object given in the parameter.', () => { + const blob = new Blob(['TEST']); + expect(URL.createObjectURL(blob).startsWith('blob:nodedata:')).toBe(true); + }); + + it('Supports Node.js Blob objects.', () => { + const blob = new NodeJSBlob(['TEST']); + expect(URL.createObjectURL(blob).startsWith('blob:nodedata:')).toBe(true); + }); + }); +}); From 86d361a0008ac950c5b5bc1b5e1f34c5beba1647 Mon Sep 17 00:00:00 2001 From: David Ortner Date: Fri, 22 Sep 2023 16:22:58 +0200 Subject: [PATCH 2/2] #1087@patch: Makes sure that HTMLUnknownElement is disconnected from its parent when replaces by a custom element. --- .../html-unknown-element/HTMLUnknownElement.ts | 2 ++ turbo.json | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) 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 d641fbcb7..02cb7a737 100644 --- a/packages/happy-dom/src/nodes/html-unknown-element/HTMLUnknownElement.ts +++ b/packages/happy-dom/src/nodes/html-unknown-element/HTMLUnknownElement.ts @@ -78,6 +78,8 @@ export default class HTMLUnknownElement extends HTMLElement implements IHTMLElem if (newElement.isConnected && newElement.connectedCallback) { newElement.connectedCallback(); } + + this._connectToNode(null); } }; callbacks[tagName] = callbacks[tagName] || []; diff --git a/turbo.json b/turbo.json index 7532515aa..a085097f4 100644 --- a/turbo.json +++ b/turbo.json @@ -12,18 +12,28 @@ "jest-environment#compile": { "dependsOn": ["happy-dom#compile"] }, + "integration-test#compile": { + "dependsOn": ["happy-dom#compile"] + }, + "uncaught-exception-observer#compile": { + "dependsOn": ["happy-dom#compile"] + }, "happy-dom#test": { "outputs": ["node_modules/vitest/**"] }, "global-registrator#test": { - "dependsOn": ["happy-dom#compile"], + "dependsOn": ["happy-dom#compile", "global-registrator#compile"], "outputs": ["tmp/**"] }, "jest-environment#test": { - "dependsOn": ["happy-dom#compile"] + "dependsOn": ["happy-dom#compile", "jest-environment#compile"] }, "integration-test#test": { - "dependsOn": ["happy-dom#compile"] + "dependsOn": ["happy-dom#compile", "integration-test#compile"] + }, + "uncaught-exception-observer#test": { + "dependsOn": ["happy-dom#compile", "uncaught-exception-observer#compile"], + "outputs": ["tmp/**"] }, "lint": { "outputs": []