feat: Reinitialize frontend with SvelteKit and TypeScript

- Delete old Vite+Svelte frontend
- Initialize new SvelteKit project with TypeScript
- Configure Tailwind CSS v4 + DaisyUI
- Implement JWT authentication with auto-refresh
- Create login page with form validation (Zod)
- Add protected route guards
- Update Docker configuration for single-stage build
- Add E2E tests with Playwright (6/11 passing)
- Fix Svelte 5 reactivity with $state() runes

Known issues:
- 5 E2E tests failing (timing/async issues)
- Token refresh implementation needs debugging
- Validation error display timing
This commit is contained in:
2026-02-17 16:19:59 -05:00
parent 54df6018f5
commit de2d83092e
28274 changed files with 3816354 additions and 90 deletions

View File

@@ -0,0 +1,70 @@
import IBrowserSettings from '../types/IBrowserSettings.js';
import DetachedBrowserContext from './DetachedBrowserContext.js';
import IOptionalBrowserSettings from '../types/IOptionalBrowserSettings.js';
import DetachedBrowserPage from './DetachedBrowserPage.js';
import IBrowser from '../types/IBrowser.js';
import IBrowserFrame from '../types/IBrowserFrame.js';
import BrowserWindow from '../../window/BrowserWindow.js';
import * as PropertySymbol from '../../PropertySymbol.js';
import BrowserExceptionObserver from '../utilities/BrowserExceptionObserver.js';
/**
* Detached browser used when constructing a Window instance without a browser.
*/
export default class DetachedBrowser implements IBrowser {
readonly contexts: DetachedBrowserContext[];
readonly settings: IBrowserSettings;
readonly console: Console | null;
readonly windowClass: new (browserFrame: IBrowserFrame, options?: {
url?: string;
width?: number;
height?: number;
}) => BrowserWindow | null;
[PropertySymbol.exceptionObserver]: BrowserExceptionObserver | null;
/**
* Constructor.
*
* @param windowClass Window class.
* @param [options] Options.
* @param [options.settings] Browser settings.
* @param [options.console] Console.
*/
constructor(windowClass: new (browserFrame: IBrowserFrame, options?: {
url?: string;
width?: number;
height?: number;
}) => BrowserWindow, options?: {
settings?: IOptionalBrowserSettings;
console?: Console;
});
/**
* Returns the default context.
*
* @returns Default context.
*/
get defaultContext(): DetachedBrowserContext;
/**
* Aborts all ongoing operations and destroys the browser.
*/
close(): Promise<void>;
/**
* Returns a promise that is resolved when all resources has been loaded, fetch has completed, and all async tasks such as timers are complete.
*
* @returns Promise.
*/
waitUntilComplete(): Promise<void>;
/**
* Aborts all ongoing operations.
*/
abort(): Promise<void>;
/**
* Creates a new incognito context.
*/
newIncognitoContext(): DetachedBrowserContext;
/**
* Creates a new page.
*
* @returns Page.
*/
newPage(): DetachedBrowserPage;
}
//# sourceMappingURL=DetachedBrowser.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"DetachedBrowser.d.ts","sourceRoot":"","sources":["../../../src/browser/detached-browser/DetachedBrowser.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,8BAA8B,CAAC;AAC5D,OAAO,sBAAsB,MAAM,6BAA6B,CAAC;AACjE,OAAO,wBAAwB,MAAM,sCAAsC,CAAC;AAE5E,OAAO,mBAAmB,MAAM,0BAA0B,CAAC;AAC3D,OAAO,QAAQ,MAAM,sBAAsB,CAAC;AAC5C,OAAO,aAAa,MAAM,2BAA2B,CAAC;AACtD,OAAO,aAAa,MAAM,+BAA+B,CAAC;AAC1D,OAAO,KAAK,cAAc,MAAM,yBAAyB,CAAC;AAE1D,OAAO,wBAAwB,MAAM,0CAA0C,CAAC;AAEhF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,eAAgB,YAAW,QAAQ;IACvD,SAAgB,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnD,SAAgB,QAAQ,EAAE,gBAAgB,CAAC;IAC3C,SAAgB,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxC,SAAgB,WAAW,EAAE,KAC5B,YAAY,EAAE,aAAa,EAC3B,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KACvD,aAAa,GAAG,IAAI,CAAC;IACnB,CAAC,cAAc,CAAC,iBAAiB,CAAC,EAAE,wBAAwB,GAAG,IAAI,CAAQ;IAElF;;;;;;;OAOG;gBAEF,WAAW,EAAE,KACZ,YAAY,EAAE,aAAa,EAC3B,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KACvD,aAAa,EAClB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,wBAAwB,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE;IAYrE;;;;OAIG;IACH,IAAW,cAAc,IAAI,sBAAsB,CAKlD;IAED;;OAEG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOnC;;;;OAIG;IACU,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAI/C;;OAEG;IACI,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa7B;;OAEG;IACI,mBAAmB,IAAI,sBAAsB;IAIpD;;;;OAIG;IACI,OAAO,IAAI,mBAAmB;CAMrC"}

View File

@@ -0,0 +1,94 @@
import DetachedBrowserContext from './DetachedBrowserContext.js';
import BrowserSettingsFactory from '../BrowserSettingsFactory.js';
import * as PropertySymbol from '../../PropertySymbol.js';
import BrowserErrorCaptureEnum from '../enums/BrowserErrorCaptureEnum.js';
import BrowserExceptionObserver from '../utilities/BrowserExceptionObserver.js';
/**
* Detached browser used when constructing a Window instance without a browser.
*/
export default class DetachedBrowser {
contexts;
settings;
console;
windowClass;
[PropertySymbol.exceptionObserver] = null;
/**
* Constructor.
*
* @param windowClass Window class.
* @param [options] Options.
* @param [options.settings] Browser settings.
* @param [options.console] Console.
*/
constructor(windowClass, options) {
this.windowClass = windowClass;
this.console = options?.console || null;
this.settings = BrowserSettingsFactory.createSettings(options?.settings);
if (this.settings.errorCapture === BrowserErrorCaptureEnum.processLevel) {
this[PropertySymbol.exceptionObserver] = new BrowserExceptionObserver();
}
this.contexts = [];
this.contexts.push(new DetachedBrowserContext(this));
}
/**
* Returns the default context.
*
* @returns Default context.
*/
get defaultContext() {
if (this.contexts.length === 0) {
throw new Error('No default context. The browser has been closed.');
}
return this.contexts[0];
}
/**
* Aborts all ongoing operations and destroys the browser.
*/
async close() {
await Promise.all(this.contexts.slice().map((context) => context.close()));
this.contexts = [];
this.console = null;
this.windowClass = null;
}
/**
* Returns a promise that is resolved when all resources has been loaded, fetch has completed, and all async tasks such as timers are complete.
*
* @returns Promise.
*/
async waitUntilComplete() {
await Promise.all(this.contexts.map((page) => page.waitUntilComplete()));
}
/**
* Aborts all ongoing operations.
*/
abort() {
// Using Promise instead of async/await to prevent microtask
return new Promise((resolve, reject) => {
if (!this.contexts.length) {
resolve();
return;
}
Promise.all(this.contexts.slice().map((context) => context.abort()))
.then(() => resolve())
.catch((error) => reject(error));
});
}
/**
* Creates a new incognito context.
*/
newIncognitoContext() {
throw new Error('Not possible to create a new context on a detached browser.');
}
/**
* Creates a new page.
*
* @returns Page.
*/
newPage() {
if (this.contexts.length === 0) {
throw new Error('No default context. The browser has been closed.');
}
return this.contexts[0].newPage();
}
}
//# sourceMappingURL=DetachedBrowser.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"DetachedBrowser.js","sourceRoot":"","sources":["../../../src/browser/detached-browser/DetachedBrowser.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,44 @@
import DetachedBrowser from './DetachedBrowser.js';
import DetachedBrowserPage from './DetachedBrowserPage.js';
import IBrowserContext from '../types/IBrowserContext.js';
import ICookieContainer from '../../cookie/ICookieContainer.js';
import IResponseCache from '../../fetch/cache/response/IResponseCache.js';
import IPreflightResponseCache from '../../fetch/cache/preflight/IPreflightResponseCache.js';
/**
* Detached browser context used when constructing a Window instance without a browser.
*/
export default class DetachedBrowserContext implements IBrowserContext {
readonly pages: DetachedBrowserPage[];
readonly browser: DetachedBrowser;
readonly cookieContainer: ICookieContainer;
readonly responseCache: IResponseCache;
readonly preflightResponseCache: IPreflightResponseCache;
/**
* Constructor.
*
* @param browser Browser.
*/
constructor(browser: DetachedBrowser);
/**
* Aborts all ongoing operations and destroys the context.
*/
close(): Promise<void>;
/**
* Returns a promise that is resolved when all resources has been loaded, fetch has completed, and all async tasks such as timers are complete.
*
* @returns Promise.
*/
waitUntilComplete(): Promise<void>;
/**
* Aborts all ongoing operations.
*/
abort(): Promise<void>;
/**
* Creates a new page.
*
* @param [opener] Opener.
* @returns Page.
*/
newPage(): DetachedBrowserPage;
}
//# sourceMappingURL=DetachedBrowserContext.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"DetachedBrowserContext.d.ts","sourceRoot":"","sources":["../../../src/browser/detached-browser/DetachedBrowserContext.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,sBAAsB,CAAC;AACnD,OAAO,mBAAmB,MAAM,0BAA0B,CAAC;AAC3D,OAAO,eAAe,MAAM,6BAA6B,CAAC;AAC1D,OAAO,gBAAgB,MAAM,kCAAkC,CAAC;AAGhE,OAAO,cAAc,MAAM,8CAA8C,CAAC;AAC1E,OAAO,uBAAuB,MAAM,wDAAwD,CAAC;AAG7F;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,sBAAuB,YAAW,eAAe;IACrE,SAAgB,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAC7C,SAAgB,OAAO,EAAE,eAAe,CAAC;IACzC,SAAgB,eAAe,EAAE,gBAAgB,CAAyB;IAC1E,SAAgB,aAAa,EAAE,cAAc,CAAuB;IACpE,SAAgB,sBAAsB,EAAE,uBAAuB,CAAgC;IAE/F;;;;OAIG;gBACS,OAAO,EAAE,eAAe;IAMpC;;OAEG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBnC;;;;OAIG;IACU,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAI/C;;OAEG;IACI,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAY7B;;;;;OAKG;IACI,OAAO,IAAI,mBAAmB;CAKrC"}

View File

@@ -0,0 +1,82 @@
import DetachedBrowserPage from './DetachedBrowserPage.js';
import CookieContainer from '../../cookie/CookieContainer.js';
import ResponseCache from '../../fetch/cache/response/ResponseCache.js';
import PreflightResponseCache from '../../fetch/cache/preflight/PreflightResponseCache.js';
/**
* Detached browser context used when constructing a Window instance without a browser.
*/
export default class DetachedBrowserContext {
pages;
browser;
cookieContainer = new CookieContainer();
responseCache = new ResponseCache();
preflightResponseCache = new PreflightResponseCache();
/**
* Constructor.
*
* @param browser Browser.
*/
constructor(browser) {
this.browser = browser;
this.pages = [];
this.pages.push(new DetachedBrowserPage(this));
}
/**
* Aborts all ongoing operations and destroys the context.
*/
async close() {
if (!this.browser) {
return;
}
await Promise.all(this.pages.slice().map((page) => page.close()));
const browser = this.browser;
const index = browser.contexts.indexOf(this);
if (index !== -1) {
browser.contexts.splice(index, 1);
}
this.pages = [];
this.browser = null;
this.cookieContainer = null;
this.responseCache.clear();
this.preflightResponseCache.clear();
this.responseCache = null;
this.preflightResponseCache = null;
if (browser.contexts.length === 0) {
browser.close();
}
}
/**
* Returns a promise that is resolved when all resources has been loaded, fetch has completed, and all async tasks such as timers are complete.
*
* @returns Promise.
*/
async waitUntilComplete() {
await Promise.all(this.pages.map((page) => page.waitUntilComplete()));
}
/**
* Aborts all ongoing operations.
*/
abort() {
return new Promise((resolve, reject) => {
if (!this.pages.length) {
resolve();
return;
}
Promise.all(this.pages.slice().map((page) => page.abort()))
.then(() => resolve())
.catch((error) => reject(error));
});
}
/**
* Creates a new page.
*
* @param [opener] Opener.
* @returns Page.
*/
newPage() {
const page = new DetachedBrowserPage(this);
this.pages.push(page);
return page;
}
}
//# sourceMappingURL=DetachedBrowserContext.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"DetachedBrowserContext.js","sourceRoot":"","sources":["../../../src/browser/detached-browser/DetachedBrowserContext.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,119 @@
import DetachedBrowserPage from './DetachedBrowserPage.js';
import * as PropertySymbol from '../../PropertySymbol.js';
import IBrowserFrame from '../types/IBrowserFrame.js';
import Response from '../../fetch/Response.js';
import IGoToOptions from '../types/IGoToOptions.js';
import { Script } from 'vm';
import BrowserWindow from '../../window/BrowserWindow.js';
import IReloadOptions from '../types/IReloadOptions.js';
import Document from '../../nodes/document/Document.js';
import CrossOriginBrowserWindow from '../../window/CrossOriginBrowserWindow.js';
import IHistoryItem from '../../history/IHistoryItem.js';
/**
* Browser frame used when constructing a Window instance without a browser.
*/
export default class DetachedBrowserFrame implements IBrowserFrame {
readonly childFrames: DetachedBrowserFrame[];
readonly parentFrame: DetachedBrowserFrame | null;
readonly page: DetachedBrowserPage;
window: BrowserWindow;
[PropertySymbol.asyncTaskManager]: any;
[PropertySymbol.listeners]: {
navigation: Array<() => void>;
};
[PropertySymbol.openerFrame]: IBrowserFrame | null;
[PropertySymbol.openerWindow]: BrowserWindow | CrossOriginBrowserWindow | null;
[PropertySymbol.popup]: boolean;
[PropertySymbol.history]: IHistoryItem[];
/**
* Constructor.
*
* @param page Page.
* @param [window] Window.
*/
constructor(page: DetachedBrowserPage);
/**
* Returns the content.
*
* @returns Content.
*/
get content(): string;
/**
* Sets the content.
*
* @param content Content.
*/
set content(content: string);
/**
* Returns the URL.
*
* @returns URL.
*/
get url(): string;
/**
* Sets the content.
*
* @param url URL.
*/
set url(url: string);
/**
* Returns document.
*
* @returns Document.
*/
get document(): Document;
/**
* Returns a promise that is resolved when all resources has been loaded, fetch has completed, and all async tasks such as timers are complete.
*/
waitUntilComplete(): Promise<void>;
/**
* Returns a promise that is resolved when the frame has navigated and the response HTML has been written to the document.
*/
waitForNavigation(): Promise<void>;
/**
* Aborts all ongoing operations.
*/
abort(): Promise<void>;
/**
* Evaluates code or a VM Script in the page's context.
*
* @param script Script.
* @returns Result.
*/
evaluate(script: string | Script): any;
/**
* Go to a page.
*
* @param url URL.
* @param [options] Options.
* @returns Response.
*/
goto(url: string, options?: IGoToOptions): Promise<Response | null>;
/**
* Navigates back in history.
*
* @param [options] Options.
*/
goBack(options?: IGoToOptions): Promise<Response | null>;
/**
* Navigates forward in history.
*
* @param [options] Options.
*/
goForward(options?: IGoToOptions): Promise<Response | null>;
/**
* Navigates a delta in history.
*
* @param steps Steps.
* @param [options] Options.
*/
goSteps(steps?: number, options?: IGoToOptions): Promise<Response | null>;
/**
* Reloads the current frame.
*
* @param [options] Options.
* @returns Response.
*/
reload(options?: IReloadOptions): Promise<Response | null>;
}
//# sourceMappingURL=DetachedBrowserFrame.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"DetachedBrowserFrame.d.ts","sourceRoot":"","sources":["../../../src/browser/detached-browser/DetachedBrowserFrame.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,cAAc,MAAM,yBAAyB,CAAC;AAE1D,OAAO,aAAa,MAAM,2BAA2B,CAAC;AACtD,OAAO,QAAQ,MAAM,yBAAyB,CAAC;AAC/C,OAAO,YAAY,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAI5B,OAAO,aAAa,MAAM,+BAA+B,CAAC;AAC1D,OAAO,cAAc,MAAM,4BAA4B,CAAC;AACxD,OAAO,QAAQ,MAAM,kCAAkC,CAAC;AACxD,OAAO,wBAAwB,MAAM,0CAA0C,CAAC;AAChF,OAAO,YAAY,MAAM,+BAA+B,CAAC;AAGzD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,oBAAqB,YAAW,aAAa;IACjE,SAAgB,WAAW,EAAE,oBAAoB,EAAE,CAAM;IACzD,SAAgB,WAAW,EAAE,oBAAoB,GAAG,IAAI,CAAQ;IAChE,SAAgB,IAAI,EAAE,mBAAmB,CAAC;IAEnC,MAAM,EAAE,aAAa,CAAC;IACtB,CAAC,cAAc,CAAC,gBAAgB,CAAC,MAA8B;IAC/D,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE;QAAE,UAAU,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAA;KAAE,CAAsB;IACnF,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,aAAa,GAAG,IAAI,CAAQ;IAC1D,CAAC,cAAc,CAAC,YAAY,CAAC,EAAE,aAAa,GAAG,wBAAwB,GAAG,IAAI,CAAQ;IACtF,CAAC,cAAc,CAAC,KAAK,CAAC,UAAS;IAC/B,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,CAU7C;IAEF;;;;;OAKG;gBACS,IAAI,EAAE,mBAAmB;IAYrC;;;;OAIG;IACH,IAAW,OAAO,IAAI,MAAM,CAK3B;IAED;;;;OAIG;IACH,IAAW,OAAO,CAAC,OAAO,EAZJ,MAYI,EAQzB;IAED;;;;OAIG;IACH,IAAW,GAAG,IAAI,MAAM,CAKvB;IAED;;;;OAIG;IACH,IAAW,GAAG,CAAC,GAAG,EAZA,MAYA,EAQjB;IAED;;;;OAIG;IACH,IAAW,QAAQ,IAAI,QAAQ,CAE9B;IAED;;OAEG;IACU,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAO/C;;OAEG;IACI,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzC;;OAEG;IACI,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB7B;;;;;OAKG;IACI,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG;IAI7C;;;;;;OAMG;IACI,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAS1E;;;;OAIG;IACI,MAAM,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAQ/D;;;;OAIG;IACI,SAAS,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAQlE;;;;;OAKG;IACI,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAShF;;;;;OAKG;IACI,MAAM,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;CAOjE"}

View File

@@ -0,0 +1,210 @@
import * as PropertySymbol from '../../PropertySymbol.js';
import AsyncTaskManager from '../../async-task-manager/AsyncTaskManager.js';
import BrowserFrameURL from '../utilities/BrowserFrameURL.js';
import BrowserFrameScriptEvaluator from '../utilities/BrowserFrameScriptEvaluator.js';
import BrowserFrameNavigator from '../utilities/BrowserFrameNavigator.js';
import HistoryScrollRestorationEnum from '../../history/HistoryScrollRestorationEnum.js';
/**
* Browser frame used when constructing a Window instance without a browser.
*/
export default class DetachedBrowserFrame {
childFrames = [];
parentFrame = null;
page;
// Needs to be injected from the outside when the browser frame is constructed.
window;
[PropertySymbol.asyncTaskManager] = new AsyncTaskManager(this);
[PropertySymbol.listeners] = { navigation: [] };
[PropertySymbol.openerFrame] = null;
[PropertySymbol.openerWindow] = null;
[PropertySymbol.popup] = false;
[PropertySymbol.history] = [
{
title: '',
href: 'about:blank',
state: null,
scrollRestoration: HistoryScrollRestorationEnum.auto,
method: 'GET',
formData: null,
isCurrent: true
}
];
/**
* Constructor.
*
* @param page Page.
* @param [window] Window.
*/
constructor(page) {
this.page = page;
if (page.context.browser.contexts[0]?.pages[0]?.mainFrame) {
this.window = new this.page.context.browser.windowClass(this);
}
// Attach process level error capturing.
if (page.context.browser[PropertySymbol.exceptionObserver]) {
page.context.browser[PropertySymbol.exceptionObserver].observe(this.window);
}
}
/**
* Returns the content.
*
* @returns Content.
*/
get content() {
if (!this.window) {
throw new Error('The frame has been destroyed, the "window" property is not set.');
}
return this.window.document.documentElement.outerHTML;
}
/**
* Sets the content.
*
* @param content Content.
*/
set content(content) {
if (!this.window) {
throw new Error('The frame has been destroyed, the "window" property is not set.');
}
this.window.document[PropertySymbol.isFirstWrite] = true;
this.window.document[PropertySymbol.isFirstWriteAfterOpen] = false;
this.window.document.open();
this.window.document.write(content);
}
/**
* Returns the URL.
*
* @returns URL.
*/
get url() {
if (!this.window) {
throw new Error('The frame has been destroyed, the "window" property is not set.');
}
return this.window.location.href;
}
/**
* Sets the content.
*
* @param url URL.
*/
set url(url) {
if (!this.window) {
throw new Error('The frame has been destroyed, the "window" property is not set.');
}
this.window[PropertySymbol.location][PropertySymbol.setURL](this, BrowserFrameURL.getRelativeURL(this, url).href);
}
/**
* Returns document.
*
* @returns Document.
*/
get document() {
return this.window?.document ?? null;
}
/**
* Returns a promise that is resolved when all resources has been loaded, fetch has completed, and all async tasks such as timers are complete.
*/
async waitUntilComplete() {
await Promise.all([
this[PropertySymbol.asyncTaskManager].waitUntilComplete(),
...this.childFrames.map((frame) => frame.waitUntilComplete())
]);
}
/**
* Returns a promise that is resolved when the frame has navigated and the response HTML has been written to the document.
*/
waitForNavigation() {
return new Promise((resolve) => this[PropertySymbol.listeners].navigation.push(resolve));
}
/**
* Aborts all ongoing operations.
*/
abort() {
if (!this.childFrames.length) {
return this[PropertySymbol.asyncTaskManager].abort();
}
return new Promise((resolve, reject) => {
// Using Promise instead of async/await to prevent microtask
Promise.all(this.childFrames
.map((frame) => frame.abort())
.concat([this[PropertySymbol.asyncTaskManager].abort()]))
.then(() => resolve())
.catch(reject);
});
}
/**
* Evaluates code or a VM Script in the page's context.
*
* @param script Script.
* @returns Result.
*/
evaluate(script) {
return BrowserFrameScriptEvaluator.evaluate(this, script);
}
/**
* Go to a page.
*
* @param url URL.
* @param [options] Options.
* @returns Response.
*/
goto(url, options) {
return BrowserFrameNavigator.navigate({
windowClass: this.page.context.browser.windowClass,
frame: this,
url: url,
goToOptions: options
});
}
/**
* Navigates back in history.
*
* @param [options] Options.
*/
goBack(options) {
return BrowserFrameNavigator.navigateBack({
windowClass: this.page.context.browser.windowClass,
frame: this,
goToOptions: options
});
}
/**
* Navigates forward in history.
*
* @param [options] Options.
*/
goForward(options) {
return BrowserFrameNavigator.navigateForward({
windowClass: this.page.context.browser.windowClass,
frame: this,
goToOptions: options
});
}
/**
* Navigates a delta in history.
*
* @param steps Steps.
* @param [options] Options.
*/
goSteps(steps, options) {
return BrowserFrameNavigator.navigateSteps({
windowClass: this.page.context.browser.windowClass,
frame: this,
steps: steps,
goToOptions: options
});
}
/**
* Reloads the current frame.
*
* @param [options] Options.
* @returns Response.
*/
reload(options) {
return BrowserFrameNavigator.reload({
windowClass: this.page.context.browser.windowClass,
frame: this,
goToOptions: options
});
}
}
//# sourceMappingURL=DetachedBrowserFrame.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"DetachedBrowserFrame.js","sourceRoot":"","sources":["../../../src/browser/detached-browser/DetachedBrowserFrame.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,117 @@
import VirtualConsolePrinter from '../../console/VirtualConsolePrinter.js';
import DetachedBrowserFrame from './DetachedBrowserFrame.js';
import DetachedBrowserContext from './DetachedBrowserContext.js';
import IBrowserPage from '../types/IBrowserPage.js';
import { Script } from 'vm';
import IGoToOptions from '../types/IGoToOptions.js';
import Response from '../../fetch/Response.js';
import IReloadOptions from '../types/IReloadOptions.js';
import IOptionalBrowserPageViewport from '../types/IOptionalBrowserPageViewport.js';
import IBrowserPageViewport from '../types/IBrowserPageViewport.js';
/**
* Detached browser page used when constructing a Window instance without a browser.
*/
export default class DetachedBrowserPage implements IBrowserPage {
readonly virtualConsolePrinter: VirtualConsolePrinter;
readonly mainFrame: DetachedBrowserFrame;
readonly context: DetachedBrowserContext;
readonly console: Console;
readonly viewport: IBrowserPageViewport;
/**
* Constructor.
*
* @param context Browser context.
*/
constructor(context: DetachedBrowserContext);
/**
* Returns frames.
*/
get frames(): DetachedBrowserFrame[];
/**
* Returns the viewport.
*/
get content(): string;
/**
* Sets the content.
*
* @param content Content.
*/
set content(content: string);
/**
* Returns the URL.
*
* @returns URL.
*/
get url(): string;
/**
* Sets the content.
*
* @param url URL.
*/
set url(url: string);
/**
* Aborts all ongoing operations and destroys the page.
*/
close(): Promise<void>;
/**
* Returns a promise that is resolved when all resources has been loaded, fetch has completed, and all async tasks such as timers are complete.
*/
waitUntilComplete(): Promise<void>;
/**
* Returns a promise that is resolved when the page has navigated and the response HTML has been written to the document.
*/
waitForNavigation(): Promise<void>;
/**
* Aborts all ongoing operations.
*/
abort(): Promise<void>;
/**
* Evaluates code or a VM Script in the page's context.
*
* @param script Script.
* @returns Result.
*/
evaluate(script: string | Script): any;
/**
* Sets the viewport.
*
* @param viewport Viewport.
*/
setViewport(viewport: IOptionalBrowserPageViewport): void;
/**
* Go to a page.
*
* @param url URL.
* @param [options] Options.
* @returns Response.
*/
goto(url: string, options?: IGoToOptions): Promise<Response | null>;
/**
* Navigates back in history.
*
* @param [options] Options.
*/
goBack(options?: IGoToOptions): Promise<Response | null>;
/**
* Navigates forward in history.
*
* @param [options] Options.
*/
goForward(options?: IGoToOptions): Promise<Response | null>;
/**
* Navigates a delta in history.
*
* @param delta Delta.
* @param steps
* @param [options] Options.
*/
goSteps(steps?: number, options?: IGoToOptions): Promise<Response | null>;
/**
* Reloads the current page.
*
* @param [options] Options.
* @returns Response.
*/
reload(options?: IReloadOptions): Promise<Response | null>;
}
//# sourceMappingURL=DetachedBrowserPage.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"DetachedBrowserPage.d.ts","sourceRoot":"","sources":["../../../src/browser/detached-browser/DetachedBrowserPage.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,MAAM,wCAAwC,CAAC;AAC3E,OAAO,oBAAoB,MAAM,2BAA2B,CAAC;AAC7D,OAAO,sBAAsB,MAAM,6BAA6B,CAAC;AAEjE,OAAO,YAAY,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,YAAY,MAAM,0BAA0B,CAAC;AACpD,OAAO,QAAQ,MAAM,yBAAyB,CAAC;AAE/C,OAAO,cAAc,MAAM,4BAA4B,CAAC;AAExD,OAAO,4BAA4B,MAAM,0CAA0C,CAAC;AACpF,OAAO,oBAAoB,MAAM,kCAAkC,CAAC;AAGpE;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAoB,YAAW,YAAY;IAC/D,SAAgB,qBAAqB,wBAA+B;IACpE,SAAgB,SAAS,EAAE,oBAAoB,CAAC;IAChD,SAAgB,OAAO,EAAE,sBAAsB,CAAC;IAChD,SAAgB,OAAO,EAAE,OAAO,CAAC;IACjC,SAAgB,QAAQ,EAAE,oBAAoB,CAAiD;IAE/F;;;;OAIG;gBACS,OAAO,EAAE,sBAAsB;IAM3C;;OAEG;IACH,IAAW,MAAM,IAAI,oBAAoB,EAAE,CAE1C;IAED;;OAEG;IACH,IAAW,OAAO,IAAI,MAAM,CAE3B;IAED;;;;OAIG;IACH,IAAW,OAAO,CAAC,OAAO,EATJ,MASI,EAEzB;IAED;;;;OAIG;IACH,IAAW,GAAG,IAAI,MAAM,CAEvB;IAED;;;;OAIG;IACH,IAAW,GAAG,CAAC,GAAG,EATA,MASA,EAEjB;IAED;;OAEG;IACI,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB7B;;OAEG;IACI,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzC;;OAEG;IACI,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzC;;OAEG;IACI,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B;;;;;OAKG;IACI,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG;IAI7C;;;;OAIG;IACI,WAAW,CAAC,QAAQ,EAAE,4BAA4B,GAAG,IAAI;IAYhE;;;;;;OAMG;IACI,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAI1E;;;;OAIG;IACI,MAAM,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAI/D;;;;OAIG;IACI,SAAS,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAIlE;;;;;;OAMG;IACI,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAIhF;;;;;OAKG;IACI,MAAM,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;CAGjE"}

View File

@@ -0,0 +1,169 @@
import VirtualConsolePrinter from '../../console/VirtualConsolePrinter.js';
import DetachedBrowserFrame from './DetachedBrowserFrame.js';
import VirtualConsole from '../../console/VirtualConsole.js';
import BrowserPageUtility from '../utilities/BrowserPageUtility.js';
import DefaultBrowserPageViewport from '../DefaultBrowserPageViewport.js';
import Event from '../../event/Event.js';
/**
* Detached browser page used when constructing a Window instance without a browser.
*/
export default class DetachedBrowserPage {
virtualConsolePrinter = new VirtualConsolePrinter();
mainFrame;
context;
console;
viewport = Object.assign({}, DefaultBrowserPageViewport);
/**
* Constructor.
*
* @param context Browser context.
*/
constructor(context) {
this.context = context;
this.console = context.browser.console ?? new VirtualConsole(this.virtualConsolePrinter);
this.mainFrame = new DetachedBrowserFrame(this);
}
/**
* Returns frames.
*/
get frames() {
return BrowserPageUtility.getFrames(this);
}
/**
* Returns the viewport.
*/
get content() {
return this.mainFrame.content;
}
/**
* Sets the content.
*
* @param content Content.
*/
set content(content) {
this.mainFrame.content = content;
}
/**
* Returns the URL.
*
* @returns URL.
*/
get url() {
return this.mainFrame.url;
}
/**
* Sets the content.
*
* @param url URL.
*/
set url(url) {
this.mainFrame.url = url;
}
/**
* Aborts all ongoing operations and destroys the page.
*/
close() {
// Using Promise instead of async/await to prevent microtask
return new Promise((resolve, reject) => {
const context = this.context;
BrowserPageUtility.closePage(this)
.then(() => {
// As we are in a detached page, a context or browser should not exist without a page as there are no references to them.
if (context.pages[0] === this) {
context.close().then(resolve).catch(reject);
}
else {
resolve();
}
})
.catch(reject);
});
}
/**
* Returns a promise that is resolved when all resources has been loaded, fetch has completed, and all async tasks such as timers are complete.
*/
waitUntilComplete() {
return this.mainFrame.waitUntilComplete();
}
/**
* Returns a promise that is resolved when the page has navigated and the response HTML has been written to the document.
*/
waitForNavigation() {
return this.mainFrame.waitForNavigation();
}
/**
* Aborts all ongoing operations.
*/
abort() {
return this.mainFrame.abort();
}
/**
* Evaluates code or a VM Script in the page's context.
*
* @param script Script.
* @returns Result.
*/
evaluate(script) {
return this.mainFrame.evaluate(script);
}
/**
* Sets the viewport.
*
* @param viewport Viewport.
*/
setViewport(viewport) {
const previousViewport = Object.assign({}, this.viewport);
Object.assign(this.viewport, viewport);
if (previousViewport.width !== this.viewport.width ||
previousViewport.height !== this.viewport.height ||
previousViewport.devicePixelRatio !== this.viewport.devicePixelRatio) {
this.mainFrame.window.dispatchEvent(new Event('resize'));
}
}
/**
* Go to a page.
*
* @param url URL.
* @param [options] Options.
* @returns Response.
*/
goto(url, options) {
return this.mainFrame.goto(url, options);
}
/**
* Navigates back in history.
*
* @param [options] Options.
*/
goBack(options) {
return this.mainFrame.goBack(options);
}
/**
* Navigates forward in history.
*
* @param [options] Options.
*/
goForward(options) {
return this.mainFrame.goForward(options);
}
/**
* Navigates a delta in history.
*
* @param delta Delta.
* @param steps
* @param [options] Options.
*/
goSteps(steps, options) {
return this.mainFrame.goSteps(steps, options);
}
/**
* Reloads the current page.
*
* @param [options] Options.
* @returns Response.
*/
reload(options) {
return this.mainFrame.reload(options);
}
}
//# sourceMappingURL=DetachedBrowserPage.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"DetachedBrowserPage.js","sourceRoot":"","sources":["../../../src/browser/detached-browser/DetachedBrowserPage.ts"],"names":[],"mappings":"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"}