Skip to content

Commit

Permalink
chore: [#320] Continues on implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
capricorn86 committed Jan 28, 2025
1 parent 8b6b720 commit a70e27a
Show file tree
Hide file tree
Showing 40 changed files with 1,188 additions and 560 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions packages/happy-dom/bin/local-server/local-server.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* eslint-disable */

const express = require('express');
const app = express();
const path = require('path');
const PORT = 3000;

app.use(express.static(path.join(__dirname, 'public')));

app.listen(PORT, () => console.log(`Server has started: http://localhost:${PORT}`));
1 change: 1 addition & 0 deletions packages/happy-dom/bin/local-server/public/imported.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
var test = /;
11 changes: 11 additions & 0 deletions packages/happy-dom/bin/local-server/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<html>

<head>
<title>Happy DOM</title>
</head>

<body>
<h1>Happy DOM</h1>
</body>

</html>
1 change: 1 addition & 0 deletions packages/happy-dom/bin/local-server/public/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import './imported.js';
3 changes: 2 additions & 1 deletion packages/happy-dom/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@
"@webref/css": "6.6.2",
"prettier": "^2.6.0",
"typescript": "^5.0.4",
"vitest": "^2.1.4"
"vitest": "^2.1.4",
"express": "^4.20.0"
},
"engines": {
"node": ">=18.0.0"
Expand Down
13 changes: 11 additions & 2 deletions packages/happy-dom/src/PropertySymbol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -379,5 +379,14 @@ export const root = Symbol('root');
export const filterNode = Symbol('filterNode');
export const customElementReactionStack = Symbol('customElementReactionStack');
export const dispatching = Symbol('dispatching');
export const moduleCache = Symbol('moduleCache');
export const preloadCache = Symbol('preloadCache');
export const modules = Symbol('modules');
export const preloads = Symbol('preloads');
export const body = Symbol('body');
export const redirect = Symbol('redirect');
export const referrerPolicy = Symbol('referrerPolicy');
export const signal = Symbol('signal');
export const bodyUsed = Symbol('bodyUsed');
export const credentials = Symbol('credentials');
export const blocking = Symbol('blocking');
export const moduleImportMap = Symbol('moduleImportMap');
export const dispatchError = Symbol('dispatchError');
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,7 @@ export default class BrowserFrameNavigator {
// Javascript protocol
if (targetURL.protocol === 'javascript:') {
if (frame && !frame.page.context.browser.settings.disableJavaScriptEvaluation) {
const readyStateManager = (<
{ [PropertySymbol.readyStateManager]: DocumentReadyStateManager }
>(<unknown>frame.window))[PropertySymbol.readyStateManager];
const readyStateManager = frame.window[PropertySymbol.readyStateManager];

readyStateManager.startTask();
const code =
Expand Down Expand Up @@ -178,9 +176,7 @@ export default class BrowserFrameNavigator {
}

// Start navigation
const readyStateManager = (<{ [PropertySymbol.readyStateManager]: DocumentReadyStateManager }>(
(<unknown>frame.window)
))[PropertySymbol.readyStateManager];
const readyStateManager = frame.window[PropertySymbol.readyStateManager];
const abortController = new frame.window.AbortController();
const timeout = frame.window.setTimeout(
() => abortController.abort(new Error('Request timed out.')),
Expand Down
42 changes: 31 additions & 11 deletions packages/happy-dom/src/event/EventTarget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import * as PropertySymbol from '../PropertySymbol.js';
import Event from './Event.js';
import IEventListenerOptions from './IEventListenerOptions.js';
import EventPhaseEnum from './EventPhaseEnum.js';
import WindowErrorUtility from '../window/WindowErrorUtility.js';
import WindowBrowserContext from '../window/WindowBrowserContext.js';
import BrowserErrorCaptureEnum from '../browser/enums/BrowserErrorCaptureEnum.js';
import TEventListener from './TEventListener.js';
Expand Down Expand Up @@ -239,7 +238,16 @@ export default class EventTarget {
!browserSettings?.disableErrorCapturing &&
browserSettings?.errorCapture === BrowserErrorCaptureEnum.tryAndCatch
) {
WindowErrorUtility.captureError(window, this[onEventName].bind(this, event));
let result: any;
try {
result = this[onEventName].call(this, event);
} catch (error) {
window[PropertySymbol.dispatchError](error);
}

if (result instanceof Promise) {
result.catch((error) => window[PropertySymbol.dispatchError](error));
}
} else {
this[onEventName].call(this, event);
}
Expand Down Expand Up @@ -273,19 +281,31 @@ export default class EventTarget {
browserSettings?.errorCapture === BrowserErrorCaptureEnum.tryAndCatch
) {
if ((<TEventListenerObject>listener).handleEvent) {
WindowErrorUtility.captureError(
window,
(<TEventListenerObject>listener).handleEvent.bind(listener, event)
);
let result: any;
try {
result = (<TEventListenerObject>listener).handleEvent.call(listener, event);
} catch (error) {
window[PropertySymbol.dispatchError](error);
}

if (result instanceof Promise) {
result.catch((error) => window[PropertySymbol.dispatchError](error));
}
} else {
WindowErrorUtility.captureError(
window,
(<TEventListenerFunction>listener).bind(this, event)
);
let result: any;
try {
result = (<TEventListenerFunction>listener).call(this, event);
} catch (error) {
window[PropertySymbol.dispatchError](error);
}

if (result instanceof Promise) {
result.catch((error) => window[PropertySymbol.dispatchError](error));
}
}
} else {
if ((<TEventListenerObject>listener).handleEvent) {
(<TEventListenerObject>listener).handleEvent(event);
(<TEventListenerObject>listener).handleEvent.call(this, event);
} else {
(<TEventListenerFunction>listener).call(this, event);
}
Expand Down
59 changes: 31 additions & 28 deletions packages/happy-dom/src/fetch/Fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { Buffer } from 'buffer';
import FetchBodyUtility from './utilities/FetchBodyUtility.js';
import IFetchInterceptor from './types/IFetchInterceptor.js';
import VirtualServerUtility from './utilities/VirtualServerUtility.js';
import PreloadedResponseStateEnum from './PreloadedResponseStateEnum.js';
import PreloadUtility from './preload/PreloadUtility.js';

const LAST_CHUNK = Buffer.from('0\r\n\r\n');

Expand Down Expand Up @@ -60,6 +60,7 @@ export default class Fetch {
private redirectCount = 0;
private disableCache: boolean;
private disableSameOriginPolicy: boolean;
private disablePreload: boolean;
#browserFrame: IBrowserFrame;
#window: BrowserWindow;
#unfilteredHeaders: Headers | null = null;
Expand All @@ -77,6 +78,7 @@ export default class Fetch {
* @param [options.disableCache] Disables the use of cached responses. It will still store the response in the cache.
* @param [options.disableSameOriginPolicy] Disables the Same-Origin policy.
* @param [options.unfilteredHeaders] Unfiltered headers - necessary for preflight requests.
* @param [options.disablePreload] Disables the use of preloaded responses.
*/
constructor(options: {
browserFrame: IBrowserFrame;
Expand All @@ -88,6 +90,7 @@ export default class Fetch {
disableCache?: boolean;
disableSameOriginPolicy?: boolean;
unfilteredHeaders?: Headers;
disablePreload?: boolean;
}) {
this.#browserFrame = options.browserFrame;
this.#window = options.window;
Expand All @@ -106,6 +109,7 @@ export default class Fetch {
this.#browserFrame.page.context.browser.settings.fetch.disableSameOriginPolicy ??
false;
this.interceptor = this.#browserFrame.page.context.browser.settings.fetch.interceptor;
this.disablePreload = options.disablePreload ?? false;
}

/**
Expand Down Expand Up @@ -167,33 +171,6 @@ export default class Fetch {
);
}

const preloadedResponse = this.#window[PropertySymbol.preloadCache].get(
this.request[PropertySymbol.url].href
);

if (
preloadedResponse &&
(preloadedResponse.state === PreloadedResponseStateEnum.loaded ||
preloadedResponse.state === PreloadedResponseStateEnum.loading)
) {
if (
preloadedResponse.options.crossOrigin === 'use-credentials' &&
this.request.credentials !== 'include'
) {
this.#browserFrame?.page?.console.warn(
`A preload for '${this.request.url}' is found, but is not used because the request credentials mode does not match. Consider taking a look at crossorigin attribute.`
);
} else {
const response = await preloadedResponse.consume();
this.#window[PropertySymbol.preloadCache].delete(this.request[PropertySymbol.url].href);
if (response) {
return response;
}
}
} else if (preloadedResponse && preloadedResponse.state === PreloadedResponseStateEnum.intial) {
preloadedResponse.state = PreloadedResponseStateEnum.loading;
}

if (!this.disableCache) {
const cachedResponse = await this.getCachedResponse();

Expand All @@ -202,6 +179,32 @@ export default class Fetch {
}
}

if (!this.disablePreload) {
const preloadKey = PreloadUtility.getKey({
url: this.request.url,
destination: 'fetch',
mode: this.request.mode,
credentialsMode: this.request.credentials
});

const preloadEntry = this.#window.document[PropertySymbol.preloads].get(preloadKey);

if (preloadEntry) {
this.#window.document[PropertySymbol.preloads].delete(preloadKey);

if (preloadEntry.response) {
return preloadEntry.response;
}

const taskID = this.#browserFrame[PropertySymbol.asyncTaskManager].startTask();
const response = await preloadEntry.onResponseAvailable();

this.#browserFrame[PropertySymbol.asyncTaskManager].endTask(taskID);

return response;
}
}

const virtualServerResponse = await this.getVirtualServerResponse();

if (virtualServerResponse) {
Expand Down
76 changes: 0 additions & 76 deletions packages/happy-dom/src/fetch/PreloadedResponse.ts

This file was deleted.

9 changes: 0 additions & 9 deletions packages/happy-dom/src/fetch/PreloadedResponseStateEnum.ts

This file was deleted.

Loading

0 comments on commit a70e27a

Please sign in to comment.