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 all 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
31 changes: 16 additions & 15 deletions package-lock.json

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

89 changes: 62 additions & 27 deletions packages/happy-dom/README.md
@@ -1,6 +1,5 @@
![Happy DOM Logo](https://github.com/capricorn86/happy-dom/raw/master/docs/happy-dom-logo.jpg)


# About

[Happy DOM](https://github.com/capricorn86/happy-dom) is a JavaScript implementation of a web browser without its graphical user interface. It includes many web standards from WHATWG [DOM](https://dom.spec.whatwg.org/) and [HTML](https://html.spec.whatwg.org/multipage/).
Expand All @@ -9,7 +8,6 @@ The goal of [Happy DOM](https://github.com/capricorn86/happy-dom) is to emulate

[Happy DOM](https://github.com/capricorn86/happy-dom) focuses heavily on performance and can be used as an alternative to [JSDOM](https://github.com/jsdom/jsdom).


### DOM Features

- Custom Elements (Web Components)
Expand All @@ -26,8 +24,6 @@ The goal of [Happy DOM](https://github.com/capricorn86/happy-dom) is to emulate

And much more..



### Works With

- [Google LitHTML](https://lit-html.polymer-project.org)
Expand All @@ -40,20 +36,14 @@ And much more..

- [Vue](https://vuejs.org/)



# Installation

```bash
npm install happy-dom
```



# Usage



## Basic Usage

A simple example of how you can use Happy DOM.
Expand All @@ -75,8 +65,6 @@ container.appendChild(button);
console.log(document.body.innerHTML);
```



## VM Context

The default Window class is a [VM context](https://nodejs.org/api/vm.html#vm_vm_createcontext_sandbox_options). A [VM context](https://nodejs.org/api/vm.html#vm_vm_createcontext_sandbox_options) will execute JavaScript code scoped within the context where the Window instance will be the global object.
Expand All @@ -85,9 +73,9 @@ The default Window class is a [VM context](https://nodejs.org/api/vm.html#vm_vm_
import { Window } from 'happy-dom';

const window = new Window({
innerWidth: 1024,
innerHeight: 768,
url: 'http://localhost:8080'
innerWidth: 1024,
innerHeight: 768,
url: 'http://localhost:8080'
});
const document = window.document;

Expand Down Expand Up @@ -146,9 +134,9 @@ The example below will show you how to setup a Node [VM context](https://nodejs.
import { Window } from 'happy-dom';

const window = new Window({
innerWidth: 1024,
innerHeight: 768,
url: 'http://localhost:8080'
innerWidth: 1024,
innerHeight: 768,
url: 'http://localhost:8080'
});
const document = window.document;

Expand Down Expand Up @@ -207,19 +195,15 @@ Will output:
console.log(document.body.querySelector('div').getInnerHTML({ includeShadowRoots: true }));
```



## Additional Features

Happy DOM exposes two functions that may be useful when working with asynchrounous code.

**whenAsyncComplete()**

Returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) that is resolved when all async tasks has been completed.

```javascript
window.happyDOM.whenAsyncComplete().then(() => {
// Do something when all async tasks are completed.
// Do something when all async tasks are completed.
});
```

Expand All @@ -229,7 +213,7 @@ This method will cancel all running async tasks.

```javascript
window.setTimeout(() => {
// This timeout will be canceled
// This timeout will be canceled
});
window.happyDOM.cancelAsync();
```
Expand All @@ -250,7 +234,60 @@ Sets the property `window.innerHeight` and dispatches a "resize" event.
window.happyDOM.setInnerHeight(768);
```

**setURL()**

Sets the property `window.location.href`.

```javascript
window.happyDOM.setURL('https://localhost:3000');
```

## Settings

Settings can be sent to the constructor or by setting them on the "window.happyDOM.settings" property.

Set by constructor:

```javascript
const window = new Window({
innerWidth: 1024,
innerHeight: 768,
url: 'https://localhost:8080',
settings: {
disableJavaScriptFileLoading: true,
disableJavaScriptEvaluation: true,
disableCSSFileLoading: true,
enableFileSystemHttpRequests: true
}
});
```

Set by property:

```javascript
const window = new Window();

window.happyDOM.settings.disableJavaScriptFileLoading = true;
window.happyDOM.settings.disableJavaScriptEvaluation = true;
window.happyDOM.settings.disableCSSFileLoading = true;
window.happyDOM.settings.enableFileSystemHttpRequests = true;
```

**disableJavaScriptFileLoading**

Set it to "true" to disable JavaScript file loading. Defaults to "false".

**disableJavaScriptEvaluation**

Set it to "true" to completely disable JavaScript evaluation. Defaults to "false".

**disableCSSFileLoading**

Set it to "true" to disable CSS file loading using the HTMLLinkElement. Defaults to "false".

**enableFileSystemHttpRequests**

Set it to "true" to enable file system HTTP requests using XMLHttpRequest. Defaults to "false".

# Performance

Expand All @@ -268,12 +305,10 @@ window.happyDOM.setInnerHeight(768);

[See how the test was done here](https://github.com/capricorn86/happy-dom-performance-test)



# Jest

Happy DOM provide with a package called [@happy-dom/jest-environment](https://github.com/capricorn86/happy-dom/tree/master/packages/jest-environment) that makes it possible to use Happy DOM with [Jest](https://jestjs.io/).

# Global Registration

Happy DOM provide with a package called [@happy-dom/global-registrator](https://github.com/capricorn86/happy-dom/tree/master/packages/global-registrator) that can register Happy DOM globally. It makes it possible to use Happy DOM for testing in a Node environment.
Happy DOM provide with a package called [@happy-dom/global-registrator](https://github.com/capricorn86/happy-dom/tree/master/packages/global-registrator) that can register Happy DOM globally. It makes it possible to use Happy DOM for testing in a Node environment.
50 changes: 24 additions & 26 deletions packages/happy-dom/src/async-task-manager/AsyncTaskManager.ts
Expand Up @@ -3,7 +3,7 @@
*/
export default class AsyncTaskManager {
private static taskID = 0;
private runningTasks: number[] = [];
private runningTasks: { [k: string]: () => void } = {};
private runningTimers: NodeJS.Timeout[] = [];
private queue: { resolve: () => void; reject: (error: Error) => void }[] = [];

Expand All @@ -24,21 +24,27 @@ export default class AsyncTaskManager {
}

/**
* Cancels all tasks.
* Ends all tasks.
*
* @param [error] Error.
*/
public cancelAll(error?: Error): void {
for (const timerID of this.runningTimers) {
global.clearTimeout(timerID);
}

const runningTimers = this.runningTimers;
const runningTasks = this.runningTasks;
const promises = this.queue;

this.runningTasks = [];
this.runningTasks = {};
this.runningTimers = [];
this.queue = [];

for (const timer of runningTimers) {
global.clearTimeout(timer);
}

for (const key of Object.keys(runningTasks)) {
runningTasks[key]();
}

for (const promise of promises) {
if (error) {
promise.reject(error);
Expand Down Expand Up @@ -67,19 +73,20 @@ export default class AsyncTaskManager {
if (index !== -1) {
this.runningTimers.splice(index, 1);
}
if (!this.runningTasks.length && !this.runningTimers.length) {
if (!Object.keys(this.runningTasks).length && !this.runningTimers.length) {
this.cancelAll();
}
}

/**
* Starts an async task.
*
* @param abortHandler Abort handler.
* @returns Task ID.
*/
public startTask(): number {
public startTask(abortHandler?: () => void): number {
const taskID = this.newTaskID();
this.runningTasks.push(taskID);
this.runningTasks[taskID] = abortHandler ? abortHandler : () => {};
return taskID;
}

Expand All @@ -89,12 +96,12 @@ export default class AsyncTaskManager {
* @param taskID Task ID.
*/
public endTask(taskID: number): void {
const index = this.runningTasks.indexOf(taskID);
if (index !== -1) {
this.runningTasks.splice(index, 1);
}
if (!this.runningTasks.length && !this.runningTimers.length) {
this.cancelAll();
if (this.runningTasks[taskID]) {
delete this.runningTasks[taskID];

if (!Object.keys(this.runningTasks).length && !this.runningTimers.length) {
this.cancelAll();
}
}
}

Expand All @@ -104,16 +111,7 @@ export default class AsyncTaskManager {
* @returns Count.
*/
public getTaskCount(): number {
return this.runningTasks.length;
}

/**
* Returns the amount of running timers.
*
* @returns Count.
*/
public getTimerCount(): number {
return this.runningTimers.length;
return Object.keys(this.runningTasks).length;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/happy-dom/src/event/IEventListener.ts
Expand Up @@ -7,7 +7,7 @@ export default interface IEventListener {
/**
* Handles event.
*
* @param type Event type.
* @param event Event.
*/
handleEvent(event: Event): void;
}
5 changes: 4 additions & 1 deletion packages/happy-dom/src/exception/DOMExceptionNameEnum.ts
Expand Up @@ -8,6 +8,9 @@ enum DOMExceptionNameEnum {
invalidNodeTypeError = 'InvalidNodeTypeError',
invalidCharacterError = 'InvalidCharacterError',
notFoundError = 'NotFoundError',
domException = 'DOMException'
securityError = 'SecurityError',
networkError = 'NetworkError',
domException = 'DOMException',
invalidAccessError = 'InvalidAccessError'
}
export default DOMExceptionNameEnum;