Skip to content

Commit

Permalink
#450@trivial: Continue on Range implementation.
Browse files Browse the repository at this point in the history
  • Loading branch information
capricorn86 committed Jun 14, 2022
1 parent 5c3774c commit a40354f
Show file tree
Hide file tree
Showing 10 changed files with 313 additions and 120 deletions.
4 changes: 2 additions & 2 deletions packages/happy-dom/.eslintrc.js
Expand Up @@ -34,12 +34,12 @@ const COMMON_CONFIG = {
'jsdoc/check-tag-names': WARN,
'jsdoc/check-types': WARN,
'jsdoc/implements-on-classes': WARN,
'jsdoc/match-description': WARN,
'jsdoc/match-description': OFF,
'jsdoc/newline-after-description': WARN,
'jsdoc/no-types': OFF,
'jsdoc/no-undefined-types': OFF,
'jsdoc/require-description': OFF,
'jsdoc/require-description-complete-sentence': WARN,
'jsdoc/require-description-complete-sentence': OFF,
'jsdoc/require-example': OFF,
'jsdoc/require-hyphen-before-param-description': [WARN, 'never'],
'jsdoc/require-param': WARN,
Expand Down
97 changes: 97 additions & 0 deletions packages/happy-dom/src/base64/Base64.ts
@@ -0,0 +1,97 @@
import DOMException from '../exception/DOMException';
import DOMExceptionNameEnum from '../exception/DOMExceptionNameEnum';

const BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';

/**
* Base64 encoding and decoding.
*/
export default class Base64 {
/**
* Creates a Base64-encoded ASCII string from a binary string (i.e., a string in which each character in the string is treated as a byte of binary data).
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/btoa
* @param data Binay data.
* @returns Base64-encoded string.
*/
public static btoa(data: unknown): string {
const str = (<string>data).toString();
if (/[^\u0000-\u00ff]/.test(str)) {
throw new DOMException(
"Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.",
DOMExceptionNameEnum.invalidCharacterError
);
}

let t = '';
let p = -6;
let a = 0;
let i = 0;
let v = 0;
let c;
while (i < str.length || p > -6) {
if (p < 0) {
if (i < str.length) {
c = str.charCodeAt(i++);
v += 8;
} else {
c = 0;
}
a = ((a & 255) << 8) | (c & 255);
p += 8;
}
t += BASE64_CHARS.charAt(v > 0 ? (a >> p) & 63 : 64);
p -= 6;
v -= 6;
}
return t;
}

/**
* Decodes a string of data which has been encoded using Base64 encoding.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/atob
* @see https://infra.spec.whatwg.org/#forgiving-base64-encode.
* @see Https://html.spec.whatwg.org/multipage/webappapis.html#btoa.
* @param data Binay string.
* @returns An ASCII string containing decoded data from encodedData.
*/
public static atob(data: unknown): string {
const str = (<string>data).toString();

if (/[^\u0000-\u00ff]/.test(str)) {
throw new DOMException(
"Failed to execute 'atob' on 'Window': The string to be decoded contains characters outside of the Latin1 range.",
DOMExceptionNameEnum.invalidCharacterError
);
}

if (/[^A-Za-z\d+/=]/.test(str) || str.length % 4 == 1) {
throw new DOMException(
"Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.",
DOMExceptionNameEnum.invalidCharacterError
);
}

let t = '';
let p = -8;
let a = 0;
let c;
let d;
for (let i = 0; i < str.length; i++) {
if ((c = BASE64_CHARS.indexOf(str.charAt(i))) < 0) {
continue;
}
a = (a << 6) | (c & 63);
if ((p += 6) >= 0) {
d = (a >> p) & 255;
if (c !== 64) {
t += String.fromCharCode(d);
}
a &= 63;
p -= 8;
}
}
return t;
}
}
61 changes: 52 additions & 9 deletions packages/happy-dom/src/nodes/node/NodeUtility.ts
Expand Up @@ -10,15 +10,18 @@ export default class NodeUtility {
/**
* Returns boolean indicating if nodeB is an inclusive ancestor of nodeA.
*
* Based on:
* https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/helpers/node.js
*
* @see https://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor
* @param nodeA Node A.
* @param nodeB Node B.
* @param ancestorNode Ancestor node.
* @param referenceNode Reference node.
* @returns "true" if following.
*/
public static isInclusiveAncestor(nodeA: INode, nodeB: INode): boolean {
let parent: INode = nodeA;
public static isInclusiveAncestor(ancestorNode: INode, referenceNode: INode): boolean {
let parent: INode = referenceNode;
while (parent) {
if (parent === nodeB) {
if (ancestorNode === parent) {
return true;
}
parent = parent.parentNode;
Expand All @@ -29,6 +32,9 @@ export default class NodeUtility {
/**
* Returns boolean indicating if nodeB is following nodeA in the document tree.
*
* Based on:
* https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/helpers/node.js
*
* @see https://dom.spec.whatwg.org/#concept-tree-following
* @param nodeA Node A.
* @param nodeB Node B.
Expand All @@ -42,13 +48,11 @@ export default class NodeUtility {
let current: INode = nodeB;

while (current) {
const nextSibling = current.nextSibling;
current = this.following(current);

if (nextSibling === nodeA) {
if (current === nodeA) {
return true;
}

current = nextSibling ? nextSibling : current.parentNode;
}

return false;
Expand All @@ -57,6 +61,9 @@ export default class NodeUtility {
/**
* Node length.
*
* Based on:
* https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/helpers/node.js
*
* @see https://dom.spec.whatwg.org/#concept-node-length
* @param node Node.
* @returns Node length.
Expand All @@ -75,4 +82,40 @@ export default class NodeUtility {
return node.childNodes.length;
}
}

/**
* Returns boolean indicating if nodeB is following nodeA in the document tree.
*
* Based on:
* https://github.com/jsdom/js-symbol-tree/blob/master/lib/SymbolTree.js#L220
*
* @param node Node.
* @param [root] Root.
* @returns Following node.
*/
private static following(node: INode, root?: INode): INode {
const firstChild = node.firstChild;

if (firstChild) {
return firstChild;
}

let current = node;

while (current) {
if (current === root) {
return null;
}

const nextSibling = current.nextSibling;

if (nextSibling) {
return nextSibling;
}

current = current.parentNode;
}

return null;
}
}
3 changes: 3 additions & 0 deletions packages/happy-dom/src/range/RangeUtility.ts
Expand Up @@ -5,6 +5,9 @@ type BoundaryPoint = { node: INode; offset: number };

/**
* Range utility.
*
* Based on:
* https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/range/boundary-point.js.
*/
export default class RangeUtility {
/**
Expand Down
20 changes: 20 additions & 0 deletions packages/happy-dom/src/window/IWindow.ts
Expand Up @@ -303,4 +303,24 @@ export default interface IWindow extends IEventTarget, NodeJS.Global {
* @returns Promise.
*/
fetch(url: string, init?: IRequestInit): Promise<IResponse>;

/**
* Creates a Base64-encoded ASCII string from a binary string (i.e., a string in which each character in the string is treated as a byte of binary data).
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/btoa
* @param data Binay data.
* @returns Base64-encoded string.
*/
btoa(data: unknown): string;

/**
* Decodes a string of data which has been encoded using Base64 encoding.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/atob
* @see https://infra.spec.whatwg.org/#forgiving-base64-encode.
* @see Https://html.spec.whatwg.org/multipage/webappapis.html#btoa.
* @param data Binay string.
* @returns An ASCII string containing decoded data from encodedData.
*/
atob(data: unknown): string;
}
30 changes: 25 additions & 5 deletions packages/happy-dom/src/window/Window.ts
Expand Up @@ -93,7 +93,7 @@ import VMGlobalPropertyScript from './VMGlobalPropertyScript';
import * as PerfHooks from 'perf_hooks';
import VM from 'vm';
import { Buffer } from 'buffer';
import { atob, btoa } from './WindowBase64';
import Base64 from '../base64/Base64';

/**
* Browser window.
Expand Down Expand Up @@ -222,10 +222,6 @@ export default class Window extends EventTarget implements IWindow {
public readonly localStorage = new Storage();
public readonly performance = PerfHooks.performance;

// Atob & btoa
public atob = atob;
public btoa = btoa;

// Node.js Globals
public ArrayBuffer;
public Boolean;
Expand Down Expand Up @@ -530,6 +526,30 @@ export default class Window extends EventTarget implements IWindow {
return await FetchHandler.fetch(this.document, url, init);
}

/**
* Creates a Base64-encoded ASCII string from a binary string (i.e., a string in which each character in the string is treated as a byte of binary data).
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/btoa
* @param data Binay data.
* @returns Base64-encoded string.
*/
public btoa(data: unknown): string {
return Base64.btoa(data);
}

/**
* Decodes a string of data which has been encoded using Base64 encoding.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/atob
* @see https://infra.spec.whatwg.org/#forgiving-base64-encode.
* @see Https://html.spec.whatwg.org/multipage/webappapis.html#btoa.
* @param data Binay string.
* @returns An ASCII string containing decoded data from encodedData.
*/
public atob(data: unknown): string {
return Base64.atob(data);
}

/**
* Setup of VM context.
*/
Expand Down
95 changes: 0 additions & 95 deletions packages/happy-dom/src/window/WindowBase64.ts

This file was deleted.

0 comments on commit a40354f

Please sign in to comment.