Skip to content

Commit

Permalink
capricorn86#521@patch: Replace URL to native module URL.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mas0nShi committed Jul 1, 2022
1 parent 6fc77aa commit d1f8256
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 197 deletions.
2 changes: 1 addition & 1 deletion packages/happy-dom/src/fetch/FetchHandler.ts
Expand Up @@ -24,7 +24,7 @@ export default class FetchHandler {
return new Promise((resolve, reject) => {
const taskID = taskManager.startTask();

NodeFetch(RelativeURL.getAbsoluteURL(document.defaultView.location, url), init)
NodeFetch(RelativeURL.getAbsoluteURL(document.defaultView.location, url).href, init)
.then((response) => {
if (taskManager.getTaskCount() === 0) {
reject(new Error('Failed to complete fetch request. Task was canceled.'));
Expand Down
5 changes: 2 additions & 3 deletions packages/happy-dom/src/fetch/ResourceFetchHandler.ts
Expand Up @@ -32,14 +32,13 @@ export default class ResourceFetchHandler {
*/
public static fetchSync(document: IDocument, url: string): string {
// We want to only load SyncRequest when it is needed to improve performance and not have direct dependencies to server side packages.
const absoluteURL = RelativeURL.getAbsoluteURL(document.defaultView.location, url);
const absoluteURL = RelativeURL.getAbsoluteURL(document.defaultView.location, url).href;
const syncRequest = require('sync-request');
const response = syncRequest('GET', absoluteURL, {
headers: {
'user-agent': document.defaultView.navigator.userAgent,
cookie: document.defaultView.document.cookie,
referer: document.defaultView.location.href,
pragma: 'no-cache'
referer: document.defaultView.location.origin
}
});

Expand Down
4 changes: 2 additions & 2 deletions packages/happy-dom/src/location/Location.ts
Expand Up @@ -8,7 +8,7 @@ export default class Location extends URL {
* Constructor.
*/
constructor() {
super('');
super('about:blank');
}

/**
Expand All @@ -17,7 +17,7 @@ export default class Location extends URL {
* @param url URL.
*/
public replace(url: string): void {
this.parse(url);
this.href = url;
}

/**
Expand Down
33 changes: 3 additions & 30 deletions packages/happy-dom/src/location/RelativeURL.ts
@@ -1,4 +1,5 @@
import Location from './Location';
import URL from './URL';

/**
* Helper class for getting the URL relative to a Location object.
Expand All @@ -10,35 +11,7 @@ export default class RelativeURL {
* @param location Location.
* @param url URL.
*/
public static getAbsoluteURL(location: Location, url: string): string {
// If the URL starts with '//' then it is a Protocol relative URL.
// Reference: https://url.spec.whatwg.org/#protocol-relative-urls.
// E.g. '//example.com/' needs to be converted to 'http://example.com/'.
if (url.startsWith('//')) {
return location.protocol + url;
}
// If the URL starts with '/' then it is a Path relative URL.
// E.g. '/example.com/' needs to be converted to 'http://example.com/'.
if (url.startsWith('/')) {
return location.origin + url;
}
// If the URL starts with 'https://' or 'http://' then it is a Absolute URL.
// E.g. 'https://example.com' needs to be converted to 'https://example.com/'.
// E.g. 'http://example.com' needs to be converted to 'http://example.com/'.
if (!url.startsWith('https://') && !url.startsWith('http://')) {
let pathname = location.pathname;
if (pathname.endsWith('/')) {
pathname = pathname.slice(0, -1);
}

return (
location.origin +
(/(.*)\/.*/.test(pathname) ? pathname.match(/(.*)\/.*/)[1] : '') +
'/' +
url
);
}

return url;
public static getAbsoluteURL(location: Location, url: string): URL {
return new URL(url, location.href);
}
}
100 changes: 2 additions & 98 deletions packages/happy-dom/src/location/URL.ts
@@ -1,102 +1,6 @@
const URL_REGEXP =
/(https?:)\/\/([-a-zA-Z0-9@:%._\+~#=]{2,256}[a-z]{2,6})(:[0-9]*)?([-a-zA-Z0-9@:%_\+.~c&//=]*)(\?[^#]*)?(#.*)?/;
const PATH_REGEXP = /([-a-zA-Z0-9@:%_\+.~c&//=]*)(\?[^#]*)?(#.*)?/;
import { URL as Url } from 'url';

/**
*
*/
export default class URL {
public protocol = '';
public hostname = '';
public port = '';
public pathname = '';
public search = '';
public hash = '';
public username = '';
public password = '';

/**
* Constructor.
*
* @param [url] URL.
*/
constructor(url?: string) {
if (url) {
this.parse(url);
}
}

/**
* Returns the entire URL as a string.
*
* @returns Href.
*/
public get href(): string {
const credentials = this.username ? `${this.username}:${this.password}@` : '';
return this.protocol + '//' + credentials + this.host + this.pathname + this.search + this.hash;
}

/**
* Sets the href.
*
* @param url URL.
*/
public set href(url: string) {
this.parse(url);
}

/**
* Returns the origin.
*
* @returns HREF.
*/
public get origin(): string {
return this.protocol + '//' + this.host;
}

/**
* Returns the entire URL as a string.
*
* @returns Host.
*/
public get host(): string {
return this.hostname + this.port;
}

/**
* Returns the entire URL as a string.
*/
public toString(): string {
return this.href;
}

/**
* Parses an URL.
*
* @param url URL.
*/
protected parse(url: string): void {
const match = url.match(URL_REGEXP);

if (match) {
const hostnamePart = match[2] ? match[2].split('@') : '';
const credentialsPart = hostnamePart.length > 1 ? hostnamePart[0].split(':') : null;

this.protocol = match[1] || '';
this.hostname = hostnamePart.length > 1 ? hostnamePart[1] : hostnamePart[0];
this.port = match[3] || '';
this.pathname = match[4] || '/';
this.search = match[5] || '';
this.hash = match[6] || '';
this.username = credentialsPart ? credentialsPart[0] : '';
this.password = credentialsPart ? credentialsPart[1] : '';
} else {
const pathMatch = url.match(PATH_REGEXP);
if (pathMatch) {
this.pathname = pathMatch[1] || '';
this.search = pathMatch[2] || '';
this.hash = pathMatch[3] || '';
}
}
}
}
export default class URL extends Url {}
6 changes: 6 additions & 0 deletions packages/happy-dom/src/location/URLSearchParams.ts
@@ -0,0 +1,6 @@
import { URLSearchParams as UrlSearchParams } from 'url';

/**
*
*/
export default class URLSearchParams extends UrlSearchParams {}
4 changes: 2 additions & 2 deletions packages/happy-dom/src/window/IWindow.ts
Expand Up @@ -37,6 +37,7 @@ import KeyboardEvent from '../event/events/KeyboardEvent';
import ProgressEvent from '../event/events/ProgressEvent';
import EventTarget from '../event/EventTarget';
import URL from '../location/URL';
import URLSearchParams from '../location/URLSearchParams';
import Location from '../location/Location';
import MutationObserver from '../mutation-observer/MutationObserver';
import DOMParser from '../dom-parser/DOMParser';
Expand Down Expand Up @@ -84,7 +85,6 @@ import Range from '../range/Range';
import MediaQueryList from '../match-media/MediaQueryList';
import DOMRect from '../nodes/element/DOMRect';
import Window from './Window';
import { URLSearchParams } from 'url';
import { Performance } from 'perf_hooks';

/**
Expand Down Expand Up @@ -150,6 +150,7 @@ export default interface IWindow extends IEventTarget, NodeJS.Global {
readonly DataTransferItem: typeof DataTransferItem;
readonly DataTransferItemList: typeof DataTransferItemList;
readonly URL: typeof URL;
readonly URLSearchParams: typeof URLSearchParams;
readonly Location: typeof Location;
readonly CustomElementRegistry: typeof CustomElementRegistry;
readonly Window: typeof Window;
Expand All @@ -163,7 +164,6 @@ export default interface IWindow extends IEventTarget, NodeJS.Global {
readonly History: typeof History;
readonly Screen: typeof Screen;
readonly Storage: typeof Storage;
readonly URLSearchParams: typeof URLSearchParams;
readonly HTMLCollection: typeof HTMLCollection;
readonly NodeList: typeof NodeList;
readonly CSSUnitValue: typeof CSSUnitValue;
Expand Down
11 changes: 5 additions & 6 deletions packages/happy-dom/src/window/Window.ts
Expand Up @@ -37,6 +37,7 @@ import KeyboardEvent from '../event/events/KeyboardEvent';
import ProgressEvent from '../event/events/ProgressEvent';
import EventTarget from '../event/EventTarget';
import URL from '../location/URL';
import URLSearchParams from '../location/URLSearchParams';
import Location from '../location/Location';
import NonImplementedEventTypes from '../event/NonImplementedEventTypes';
import MutationObserver from '../mutation-observer/MutationObserver';
Expand Down Expand Up @@ -86,7 +87,6 @@ import MimeType from '../navigator/MimeType';
import MimeTypeArray from '../navigator/MimeTypeArray';
import Plugin from '../navigator/Plugin';
import PluginArray from '../navigator/PluginArray';
import { URLSearchParams } from 'url';
import FetchHandler from '../fetch/FetchHandler';
import { default as RangeImplementation } from '../range/Range';
import DOMRect from '../nodes/element/DOMRect';
Expand Down Expand Up @@ -209,11 +209,6 @@ export default class Window extends EventTarget implements IWindow {
public readonly FileReader;
public readonly Image;

// XMLHttpRequest
public XMLHttpRequest = XMLHttpRequest;
public XMLHttpRequestUpload = XMLHttpRequestUpload;
public XMLHttpRequestEventTarget = XMLHttpRequestEventTarget;

// Events
public onload: (event: Event) => void = null;
public onerror: (event: ErrorEvent) => void = null;
Expand All @@ -238,6 +233,10 @@ export default class Window extends EventTarget implements IWindow {
public readonly localStorage = new Storage();
public readonly performance = PerfHooks.performance;

public XMLHttpRequest = XMLHttpRequest;
public XMLHttpRequestUpload = XMLHttpRequestUpload;
public XMLHttpRequestEventTarget = XMLHttpRequestEventTarget;

// Node.js Globals
public ArrayBuffer;
public Boolean;
Expand Down

0 comments on commit d1f8256

Please sign in to comment.