Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#463@minor: Added partial support for XMLHttpRequest. #520

Merged
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
18b0bd6
#463@minor: Added partial support for XMLHttpRequest.
Mas0nShi Jun 25, 2022
3e67605
#514@patch: Fixes method getAbsoluteURL.
Mas0nShi Jun 26, 2022
30b4860
#463@minor: Continue added partial support for XMLHttpRequest.
Mas0nShi Jun 26, 2022
9d9b455
#463@minor: Continue added partial support for XMLHttpRequest.
Mas0nShi Jun 26, 2022
e01541e
#463@minor: Continue added partial support for XMLHttpRequest.
Mas0nShi Jun 26, 2022
4d5f54c
#522@patch: Fixes resource load error when websites enabled anti-thef…
Mas0nShi Jun 27, 2022
da34ce5
#463@minor: Continue added partial support for XMLHttpRequest.
Mas0nShi Jun 28, 2022
6fc77aa
Merge branch 'master' into 463-adds-support-for-xml-http-request
Mas0nShi Jul 1, 2022
d1f8256
#521@patch: Replace URL to native module URL.
Mas0nShi Jul 1, 2022
a1c0e81
#521@patch: Fixes test units error.
Mas0nShi Jul 1, 2022
9f9df58
#521@minor: Continue added partial support for XMLHttpRequest.
Mas0nShi Jul 1, 2022
a71819f
#526@minor: Adds support for Document.documentURI and Document.URL.
Mas0nShi Jul 1, 2022
1ff5b9a
#526@minor: Continue Adds support for XMLHttpRequest (Sync) and remov…
Mas0nShi Jul 3, 2022
bda8a93
#463@trivial: Continues on XMLHttpRequest implementation.
daveed07 Oct 11, 2022
fc8a845
#526@minor: Fixes problem.
Mas0nShi Oct 15, 2022
40cd3c1
#526@minor: Continue Fixes Problem.
Mas0nShi Oct 16, 2022
f517c8f
Merge remote-tracking branch 'origin/master' into 463-adds-support-fo…
Mas0nShi Oct 16, 2022
9cce579
#526@minor: Continue Fixes Problem.
Mas0nShi Oct 16, 2022
b72cdd9
#526@minor: Continue Fixes Problem.
Mas0nShi Oct 16, 2022
608b717
#526@minor: Continue Fixes Problem.
Mas0nShi Oct 16, 2022
855ed45
#463@minor: Continue Fixes Problem.
Mas0nShi Oct 16, 2022
aaf8673
#463@minor: Continue Fixes Problem.
Mas0nShi Oct 16, 2022
2ee990e
#463@minor: Found Bugs in CookieJar, add more support for syncRequest.
Mas0nShi Oct 16, 2022
7f55543
#463@minor: Found Bugs in CookieJar, add more support for syncRequest.
Mas0nShi Oct 16, 2022
d588d3b
#463@minor: Found Bugs in CookieJar, add more support for syncRequest.
Mas0nShi Oct 16, 2022
3431208
#463@minor: Continue Fixes.
Mas0nShi Oct 16, 2022
a4b22ea
#463@minor: Continue Fixes.
Mas0nShi Oct 16, 2022
f67f67d
#463@trivial: Disables HTTP request local filesystem by default and i…
daveed07 Oct 18, 2022
861690a
#463@trivial: Removes unused dependency.
capricorn86 Oct 18, 2022
9c23e1e
Merge branch 'master' into 463-adds-support-for-xml-http-request
Mas0nShi Oct 19, 2022
6f8d5dd
#520@minor: Fixes syntax error.
Mas0nShi Oct 20, 2022
3a7f974
#520@minor: Optimize the code.
Mas0nShi Oct 21, 2022
941450c
#520@minor: Optimize the code.
Mas0nShi Oct 21, 2022
1646f8e
#520@minor: Continue to improve XMLHttpRequest.
Mas0nShi Oct 22, 2022
a981b8b
Merge branch 'master' into 463-adds-support-for-xml-http-request
Mas0nShi Oct 25, 2022
677a376
#463@trivial: Continue on XMLHttpRequest implementation.
daveed07 Oct 26, 2022
9b0b6ea
#463@trivial: Continue on XMLHttpRequest implementation.
capricorn86 Nov 14, 2022
929fbd3
Merge branch 'capricorn86:master' into 463-adds-support-for-xml-http-…
Mas0nShi Nov 28, 2022
e7bb2bc
#463@trivial: Continues on XMLHttpRequest implementation.
capricorn86 Dec 3, 2022
ca00cb5
#463@trivial: Continues on XMLHttpRequest implementation.
capricorn86 Dec 5, 2022
b1b7493
Merge branch 'master' into 463-adds-support-for-xml-http-request
Mas0nShi Dec 6, 2022
96682af
#520@patch: Fixes cookie setting.
Mas0nShi Dec 6, 2022
b670ae6
#463@trivial: Continues on XMLHttpRequest implementation.
capricorn86 Dec 6, 2022
2193f38
#463@trivial: Continues on XMLHttpRequest implementation.
capricorn86 Dec 6, 2022
7bf4bd5
#463@trivial: Continues on XMLHttpRequest implementation.
capricorn86 Dec 7, 2022
2e45e3e
#463@trivial: Continues on XMLHttpRequest implementation.
capricorn86 Dec 7, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/happy-dom/src/exception/DOMExceptionNameEnum.ts
Expand Up @@ -7,6 +7,8 @@ enum DOMExceptionNameEnum {
wrongDocumentError = 'WrongDocumentError',
invalidNodeTypeError = 'InvalidNodeTypeError',
invalidCharacterError = 'InvalidCharacterError',
notFoundError = 'NotFoundError'
notFoundError = 'NotFoundError',
securityError = 'SecurityError',
networkError = 'NetworkError'
}
export default DOMExceptionNameEnum;
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
10 changes: 8 additions & 2 deletions packages/happy-dom/src/fetch/ResourceFetchHandler.ts
Expand Up @@ -32,9 +32,15 @@ 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);
const response = syncRequest('GET', absoluteURL, {
headers: {
'user-agent': document.defaultView.navigator.userAgent,
cookie: document.defaultView.document.cookie,
referer: document.defaultView.location.origin
}
});

if (response.isError()) {
throw new DOMException(
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');
Mas0nShi marked this conversation as resolved.
Show resolved Hide resolved
}

/**
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
17 changes: 3 additions & 14 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,19 +11,7 @@ export default class RelativeURL {
* @param location Location.
* @param url URL.
*/
public static getAbsoluteURL(location: Location, url: string): string {
if (url.startsWith('/')) {
return location.origin + url;
}

if (!url.startsWith('https://') && !url.startsWith('http://')) {
let pathname = location.pathname;
if (pathname.endsWith('/')) {
pathname = pathname.slice(0, -1);
}
return location.origin + pathname + '/' + 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
10 changes: 9 additions & 1 deletion 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,14 +87,16 @@ 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';
import VMGlobalPropertyScript from './VMGlobalPropertyScript';
import * as PerfHooks from 'perf_hooks';
import VM from 'vm';
import { Buffer } from 'buffer';
import XMLHttpRequest from '../xml-http-request/XMLHttpRequest';
import XMLHttpRequestUpload from '../xml-http-request/XMLHttpRequestUpload';
import { XMLHttpRequestEventTarget } from '../xml-http-request/XMLHttpRequestEventTarget';
import Base64 from '../base64/Base64';
import IDocument from '../nodes/document/IDocument';

Expand Down Expand Up @@ -230,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 Expand Up @@ -338,6 +345,7 @@ export default class Window extends EventTarget implements IWindow {
}
}

XMLHttpRequest._defaultView = this;
HTMLDocument._defaultView = this;

const document = new HTMLDocument();
Expand Down
13 changes: 13 additions & 0 deletions packages/happy-dom/src/xml-http-request/XMLHttpReqeustUtility.ts
@@ -0,0 +1,13 @@
const NodeVersion = process.version.replace('v', '').split('.');

export interface IXMLHttpRequestOptions {
anon?: boolean;
}

export const MajorNodeVersion = Number.parseInt(NodeVersion[0]);
export const copyToArrayBuffer = (buffer: Buffer, offset?: number): ArrayBuffer => {
const arrayBuffer = new ArrayBuffer(buffer.length);
const view = new Uint8Array(arrayBuffer);
view.set(buffer, offset || 0);
return arrayBuffer;
};