Update dashboard, kb, memory +4 more (+28 ~18 -1)

This commit is contained in:
Echo
2026-02-06 14:25:10 +00:00
parent 7f64d5054a
commit 19d178268a
6767 changed files with 1346472 additions and 1282 deletions

373
node_modules/jsdom/lib/api.js generated vendored Normal file
View File

@@ -0,0 +1,373 @@
"use strict";
const path = require("path");
const { pathToFileURL } = require("url");
const fs = require("fs").promises;
const vm = require("vm");
const toughCookie = require("tough-cookie");
const sniffHTMLEncoding = require("html-encoding-sniffer");
const whatwgURL = require("whatwg-url");
const { legacyHookDecode } = require("@exodus/bytes/encoding.js");
const { URL } = require("whatwg-url");
const { MIMEType } = require("whatwg-mimetype");
const { getGlobalDispatcher } = require("undici");
const idlUtils = require("./jsdom/living/generated/utils.js");
const VirtualConsole = require("./jsdom/virtual-console.js");
const { createWindow } = require("./jsdom/browser/Window.js");
const { parseIntoDocument } = require("./jsdom/browser/parser");
const { fragmentSerialization } = require("./jsdom/living/domparsing/serialization.js");
const createDecompressInterceptor = require("./jsdom/browser/resources/decompress-interceptor.js");
const {
JSDOMDispatcher, DEFAULT_USER_AGENT, fetchCollected
} = require("./jsdom/browser/resources/jsdom-dispatcher.js");
const requestInterceptor = require("./jsdom/browser/resources/request-interceptor.js");
class CookieJar extends toughCookie.CookieJar {
constructor(store, options) {
// jsdom cookie jars must be loose by default
super(store, { looseMode: true, ...options });
}
}
const window = Symbol("window");
let sharedFragmentDocument = null;
class JSDOM {
constructor(input = "", options = {}) {
const mimeType = new MIMEType(options.contentType === undefined ? "text/html" : options.contentType);
const { html, encoding } = normalizeHTML(input, mimeType);
options = transformOptions(options, encoding, mimeType);
this[window] = createWindow(options.windowOptions);
const documentImpl = idlUtils.implForWrapper(this[window]._document);
options.beforeParse(this[window]._globalProxy);
parseIntoDocument(html, documentImpl);
documentImpl.close();
}
get window() {
// It's important to grab the global proxy, instead of just the result of `createWindow(...)`, since otherwise
// things like `window.eval` don't exist.
return this[window]._globalProxy;
}
get virtualConsole() {
return this[window]._virtualConsole;
}
get cookieJar() {
// TODO NEWAPI move _cookieJar to window probably
return idlUtils.implForWrapper(this[window]._document)._cookieJar;
}
serialize() {
return fragmentSerialization(idlUtils.implForWrapper(this[window]._document), { requireWellFormed: false });
}
nodeLocation(node) {
if (!idlUtils.implForWrapper(this[window]._document)._parseOptions.sourceCodeLocationInfo) {
throw new Error("Location information was not saved for this jsdom. Use includeNodeLocations during creation.");
}
return idlUtils.implForWrapper(node).sourceCodeLocation;
}
getInternalVMContext() {
if (!vm.isContext(this[window])) {
throw new TypeError("This jsdom was not configured to allow script running. " +
"Use the runScripts option during creation.");
}
return this[window];
}
reconfigure(settings) {
if ("windowTop" in settings) {
this[window]._top = settings.windowTop;
}
if ("url" in settings) {
const document = idlUtils.implForWrapper(this[window]._document);
const url = whatwgURL.parseURL(settings.url);
if (url === null) {
throw new TypeError(`Could not parse "${settings.url}" as a URL`);
}
document._URL = url;
document._origin = whatwgURL.serializeURLOrigin(document._URL);
this[window]._sessionHistory.currentEntry.url = url;
document._clearBaseURLCache();
}
}
static fragment(string = "") {
if (!sharedFragmentDocument) {
sharedFragmentDocument = (new JSDOM()).window.document;
}
const template = sharedFragmentDocument.createElement("template");
template.innerHTML = string;
return template.content;
}
static async fromURL(url, options = {}) {
options = normalizeFromURLOptions(options);
// Build the dispatcher for the initial request
// For the initial fetch, we default to "usable" instead of no resource loading, since fromURL() implicitly requests
// fetching the initial resource. This does not impact further resource fetching, which uses options.resources.
const resourcesForInitialFetch = options.resources !== undefined ? options.resources : "usable";
const { effectiveDispatcher } = extractResourcesOptions(resourcesForInitialFetch, options.cookieJar);
const headers = { Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" };
if (options.referrer) {
headers.Referer = options.referrer;
}
const response = await fetchCollected(effectiveDispatcher, {
url,
headers
});
if (!response.ok) {
throw new Error(`Resource was not loaded. Status: ${response.status}`);
}
options = Object.assign(options, {
url: response.url,
contentType: response.headers["content-type"] || undefined,
referrer: options.referrer,
resources: options.resources
});
return new JSDOM(response.body, options);
}
static async fromFile(filename, options = {}) {
options = normalizeFromFileOptions(filename, options);
const nodeBuffer = await fs.readFile(filename);
return new JSDOM(nodeBuffer, options);
}
}
function normalizeFromURLOptions(options) {
// Checks on options that are invalid for `fromURL`
if (options.url !== undefined) {
throw new TypeError("Cannot supply a url option when using fromURL");
}
if (options.contentType !== undefined) {
throw new TypeError("Cannot supply a contentType option when using fromURL");
}
// Normalization of options which must be done before the rest of the fromURL code can use them, because they are
// given to request()
const normalized = { ...options };
if (options.referrer !== undefined) {
normalized.referrer = (new URL(options.referrer)).href;
}
if (options.cookieJar === undefined) {
normalized.cookieJar = new CookieJar();
}
return normalized;
// All other options don't need to be processed yet, and can be taken care of in the normal course of things when
// `fromURL` calls `new JSDOM(html, options)`.
}
function extractResourcesOptions(resources, cookieJar) {
// loadSubresources controls whether PerDocumentResourceLoader fetches scripts, stylesheets, etc.
// XHR always works regardless of this flag.
let userAgent, baseDispatcher, userInterceptors, loadSubresources;
if (resources === undefined) {
// resources: undefined means no automatic subresource fetching, but XHR still works
userAgent = DEFAULT_USER_AGENT;
baseDispatcher = getGlobalDispatcher();
userInterceptors = [];
loadSubresources = false;
} else if (resources === "usable") {
// resources: "usable" means use all defaults
userAgent = DEFAULT_USER_AGENT;
baseDispatcher = getGlobalDispatcher();
userInterceptors = [];
loadSubresources = true;
} else if (typeof resources === "object" && resources !== null) {
// resources: { userAgent?, dispatcher?, interceptors? }
userAgent = resources.userAgent !== undefined ? resources.userAgent : DEFAULT_USER_AGENT;
baseDispatcher = resources.dispatcher !== undefined ? resources.dispatcher : getGlobalDispatcher();
userInterceptors = resources.interceptors !== undefined ? resources.interceptors : [];
loadSubresources = true;
} else {
throw new TypeError(`resources must be undefined, "usable", or an object`);
}
// User interceptors come first (outermost), then decompress interceptor
const allUserInterceptors = [
...userInterceptors,
createDecompressInterceptor()
];
return {
userAgent,
effectiveDispatcher: new JSDOMDispatcher({
baseDispatcher,
cookieJar,
userAgent,
userInterceptors: allUserInterceptors
}),
loadSubresources
};
}
function normalizeFromFileOptions(filename, options) {
const normalized = { ...options };
if (normalized.contentType === undefined) {
const extname = path.extname(filename);
if (extname === ".xhtml" || extname === ".xht" || extname === ".xml") {
normalized.contentType = "application/xhtml+xml";
}
}
if (normalized.url === undefined) {
normalized.url = pathToFileURL(path.resolve(filename)).href;
}
return normalized;
}
function transformOptions(options, encoding, mimeType) {
const transformed = {
windowOptions: {
// Defaults
url: "about:blank",
referrer: "",
contentType: "text/html",
parsingMode: "html",
parseOptions: {
sourceCodeLocationInfo: false,
scriptingEnabled: false
},
runScripts: undefined,
encoding,
pretendToBeVisual: false,
storageQuota: 5000000,
// Defaults filled in later
dispatcher: undefined,
loadSubresources: undefined,
userAgent: undefined,
virtualConsole: undefined,
cookieJar: undefined
},
// Defaults
beforeParse() { }
};
// options.contentType was parsed into mimeType by the caller.
if (!mimeType.isHTML() && !mimeType.isXML()) {
throw new RangeError(`The given content type of "${options.contentType}" was not a HTML or XML content type`);
}
transformed.windowOptions.contentType = mimeType.essence;
transformed.windowOptions.parsingMode = mimeType.isHTML() ? "html" : "xml";
if (options.url !== undefined) {
transformed.windowOptions.url = (new URL(options.url)).href;
}
if (options.referrer !== undefined) {
transformed.windowOptions.referrer = (new URL(options.referrer)).href;
}
if (options.includeNodeLocations) {
if (transformed.windowOptions.parsingMode === "xml") {
throw new TypeError("Cannot set includeNodeLocations to true with an XML content type");
}
transformed.windowOptions.parseOptions = { sourceCodeLocationInfo: true };
}
transformed.windowOptions.cookieJar = options.cookieJar === undefined ?
new CookieJar() :
options.cookieJar;
transformed.windowOptions.virtualConsole = options.virtualConsole === undefined ?
(new VirtualConsole()).forwardTo(console) :
options.virtualConsole;
if (!(transformed.windowOptions.virtualConsole instanceof VirtualConsole)) {
throw new TypeError("virtualConsole must be an instance of VirtualConsole");
}
const { userAgent, effectiveDispatcher, loadSubresources } =
extractResourcesOptions(options.resources, transformed.windowOptions.cookieJar);
transformed.windowOptions.userAgent = userAgent;
transformed.windowOptions.dispatcher = effectiveDispatcher;
transformed.windowOptions.loadSubresources = loadSubresources;
if (options.runScripts !== undefined) {
transformed.windowOptions.runScripts = String(options.runScripts);
if (transformed.windowOptions.runScripts === "dangerously") {
transformed.windowOptions.parseOptions.scriptingEnabled = true;
} else if (transformed.windowOptions.runScripts !== "outside-only") {
throw new RangeError(`runScripts must be undefined, "dangerously", or "outside-only"`);
}
}
if (options.beforeParse !== undefined) {
transformed.beforeParse = options.beforeParse;
}
if (options.pretendToBeVisual !== undefined) {
transformed.windowOptions.pretendToBeVisual = Boolean(options.pretendToBeVisual);
}
if (options.storageQuota !== undefined) {
transformed.windowOptions.storageQuota = Number(options.storageQuota);
}
return transformed;
}
function normalizeHTML(html, mimeType) {
let encoding = "UTF-8";
if (html instanceof Uint8Array) {
// leave as-is
} else if (ArrayBuffer.isView(html)) {
html = new Uint8Array(html.buffer, html.byteOffset, html.byteLength);
} else if (html instanceof ArrayBuffer) {
html = new Uint8Array(html);
}
if (html instanceof Uint8Array) {
encoding = sniffHTMLEncoding(html, {
xml: mimeType.isXML(),
transportLayerEncodingLabel: mimeType.parameters.get("charset")
});
html = legacyHookDecode(html, encoding);
} else {
html = String(html);
}
return { html, encoding };
}
exports.JSDOM = JSDOM;
exports.VirtualConsole = VirtualConsole;
exports.CookieJar = CookieJar;
exports.requestInterceptor = requestInterceptor;
exports.toughCookie = toughCookie;

1024
node_modules/jsdom/lib/jsdom/browser/Window.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,415 @@
/* Omitting the below because of https://github.com/jsdom/cssstyle/issues/193.
And we don't implement namespace constraints anyway.
@namespace "http://www.w3.org/1999/xhtml";
*/
/* https://html.spec.whatwg.org/multipage/rendering.html#the-page */
html, body { display: block; }
/* https://html.spec.whatwg.org/multipage/rendering.html#flow-content-3
- Omits presentational hints
- Omits quirks mode
*/
address, blockquote, center, dialog, div, figure, figcaption, footer, form,
header, hr, legend, listing, main, p, plaintext, pre, search, xmp {
display: block;
}
blockquote, figure, listing, p, plaintext, pre, xmp {
margin-block: 1em;
}
blockquote, figure { margin-inline: 40px; }
address { font-style: italic; }
listing, plaintext, pre, xmp {
font-family: monospace; white-space: pre;
}
dialog:not([open]) { display: none; }
dialog {
position: absolute;
inset-inline-start: 0; inset-inline-end: 0;
width: fit-content;
height: fit-content;
margin: auto;
border: solid;
padding: 1em;
background-color: Canvas;
color: CanvasText;
}
dialog:modal {
position: fixed;
overflow: auto;
inset-block: 0;
max-width: calc(100% - 6px - 2em);
max-height: calc(100% - 6px - 2em);
}
dialog::backdrop {
background: rgba(0,0,0,0.1);
}
[popover]:not(:popover-open):not(dialog[open]) {
display:none;
}
dialog:popover-open {
display:block;
}
[popover] {
position: fixed;
inset: 0;
width: fit-content;
height: fit-content;
margin: auto;
border: solid;
padding: 0.25em;
overflow: auto;
color: CanvasText;
background-color: Canvas;
}
:popover-open::backdrop {
position: fixed;
inset: 0;
pointer-events: none !important;
background-color: transparent;
}
slot {
display: contents;
}
/* https://html.spec.whatwg.org/multipage/rendering.html#phrasing-content-3
- Omits presentational hints
*/
cite, dfn, em, i, var { font-style: italic; }
b, strong { font-weight: bolder; }
code, kbd, samp, tt { font-family: monospace; }
big { font-size: larger; }
small { font-size: smaller; }
sub { vertical-align: sub; }
sup { vertical-align: super; }
sub, sup { line-height: normal; font-size: smaller; }
ruby { display: ruby; }
rt { display: ruby-text; }
:link { color: #0000EE; }
:visited { color: #551A8B; }
:link:active, :visited:active { color: #FF0000; }
:link, :visited { text-decoration: underline; cursor: pointer; }
:focus-visible { outline: auto; }
mark { background: yellow; color: black; } /* this color is just a suggestion and can be changed based on implementation feedback */
abbr[title], acronym[title] { text-decoration: dotted underline; }
ins, u { text-decoration: underline; }
del, s, strike { text-decoration: line-through; }
q::before { content: open-quote; }
q::after { content: close-quote; }
br { display-outside: newline; } /* this also has bidi implications */
nobr { white-space: nowrap; }
wbr { display-outside: break-opportunity; } /* this also has bidi implications */
nobr wbr { white-space: normal; }
/* https://html.spec.whatwg.org/multipage/rendering.html#bidi-rendering
- Omits ISO-8859-8
*/
[dir]:dir(ltr), bdi:dir(ltr), input[type=tel i]:dir(ltr) { direction: ltr; }
[dir]:dir(rtl), bdi:dir(rtl) { direction: rtl; }
address, blockquote, center, div, figure, figcaption, footer, form, header, hr,
legend, listing, main, p, plaintext, pre, summary, xmp, article, aside, h1, h2,
h3, h4, h5, h6, hgroup, nav, section, search, table, caption, colgroup, col,
thead, tbody, tfoot, tr, td, th, dir, dd, dl, dt, menu, ol, ul, li, bdi, output,
[dir=ltr i], [dir=rtl i], [dir=auto i] {
unicode-bidi: isolate;
}
bdo, bdo[dir] { unicode-bidi: isolate-override; }
input[dir=auto i]:is([type=search i], [type=tel i], [type=url i],
[type=email i]), textarea[dir=auto i], pre[dir=auto i] {
unicode-bidi: plaintext;
}
/* see prose for input elements whose type attribute is in the Text state */
/* the rules setting the 'content' property on br and wbr elements also has bidi implications */
/* https://html.spec.whatwg.org/multipage/rendering.html#sections-and-headings
- Special h1 styles removed per upcoming change: https://github.com/whatwg/html/pull/11102
*/
article, aside, h1, h2, h3, h4, h5, h6, hgroup, nav, section {
display: block;
}
h1 { margin-block: 0.67em; font-size: 2.00em; font-weight: bold; }
h2 { margin-block: 0.83em; font-size: 1.50em; font-weight: bold; }
h3 { margin-block: 1.00em; font-size: 1.17em; font-weight: bold; }
h4 { margin-block: 1.33em; font-size: 1.00em; font-weight: bold; }
h5 { margin-block: 1.67em; font-size: 0.83em; font-weight: bold; }
h6 { margin-block: 2.33em; font-size: 0.67em; font-weight: bold; }
/* https://html.spec.whatwg.org/multipage/rendering.html#lists
- Omit presentational hints
- Omit quirks mode
*/
dir, dd, dl, dt, menu, ol, ul { display: block; }
li { display: list-item; text-align: match-parent; }
dir, dl, menu, ol, ul { margin-block: 1em; }
:is(dir, dl, menu, ol, ul) :is(dir, dl, menu, ol, ul) {
margin-block: 0;
}
dd { margin-inline-start: 40px; }
dir, menu, ol, ul { padding-inline-start: 40px; }
ol, ul, menu { counter-reset: list-item; }
ol { list-style-type: decimal; }
dir, menu, ul {
list-style-type: disc;
}
:is(dir, menu, ol, ul) :is(dir, menu, ul) {
list-style-type: circle;
}
:is(dir, menu, ol, ul) :is(dir, menu, ol, ul) :is(dir, menu, ul) {
list-style-type: square;
}
/* https://html.spec.whatwg.org/multipage/rendering.html#tables-2
- Omit presentational hints
- Omit quirks mode
- Omit HTML documents
*/
table { display: table; }
caption { display: table-caption; }
colgroup, colgroup[hidden] { display: table-column-group; }
col, col[hidden] { display: table-column; }
thead, thead[hidden] { display: table-header-group; }
tbody, tbody[hidden] { display: table-row-group; }
tfoot, tfoot[hidden] { display: table-footer-group; }
tr, tr[hidden] { display: table-row; }
td, th { display: table-cell; }
colgroup[hidden], col[hidden], thead[hidden], tbody[hidden],
tfoot[hidden], tr[hidden] {
visibility: collapse;
}
table {
box-sizing: border-box;
border-spacing: 2px;
border-collapse: separate;
text-indent: initial;
}
td, th { padding: 1px; }
th { font-weight: bold; }
caption { text-align: center; }
thead, tbody, tfoot, table > tr { vertical-align: middle; }
tr, td, th { vertical-align: inherit; }
thead, tbody, tfoot, tr { border-color: inherit; }
table[rules=none i], table[rules=groups i], table[rules=rows i],
table[rules=cols i], table[rules=all i], table[frame=void i],
table[frame=above i], table[frame=below i], table[frame=hsides i],
table[frame=lhs i], table[frame=rhs i], table[frame=vsides i],
table[frame=box i], table[frame=border i],
table[rules=none i] > tr > td, table[rules=none i] > tr > th,
table[rules=groups i] > tr > td, table[rules=groups i] > tr > th,
table[rules=rows i] > tr > td, table[rules=rows i] > tr > th,
table[rules=cols i] > tr > td, table[rules=cols i] > tr > th,
table[rules=all i] > tr > td, table[rules=all i] > tr > th,
table[rules=none i] > thead > tr > td, table[rules=none i] > thead > tr > th,
table[rules=groups i] > thead > tr > td, table[rules=groups i] > thead > tr > th,
table[rules=rows i] > thead > tr > td, table[rules=rows i] > thead > tr > th,
table[rules=cols i] > thead > tr > td, table[rules=cols i] > thead > tr > th,
table[rules=all i] > thead > tr > td, table[rules=all i] > thead > tr > th,
table[rules=none i] > tbody > tr > td, table[rules=none i] > tbody > tr > th,
table[rules=groups i] > tbody > tr > td, table[rules=groups i] > tbody > tr > th,
table[rules=rows i] > tbody > tr > td, table[rules=rows i] > tbody > tr > th,
table[rules=cols i] > tbody > tr > td, table[rules=cols i] > tbody > tr > th,
table[rules=all i] > tbody > tr > td, table[rules=all i] > tbody > tr > th,
table[rules=none i] > tfoot > tr > td, table[rules=none i] > tfoot > tr > th,
table[rules=groups i] > tfoot > tr > td, table[rules=groups i] > tfoot > tr > th,
table[rules=rows i] > tfoot > tr > td, table[rules=rows i] > tfoot > tr > th,
table[rules=cols i] > tfoot > tr > td, table[rules=cols i] > tfoot > tr > th,
table[rules=all i] > tfoot > tr > td, table[rules=all i] > tfoot > tr > th {
border-color: black;
}
/* https://html.spec.whatwg.org/multipage/rendering.html#form-controls
- Omit quirks mode
*/
input, select, button, textarea {
letter-spacing: initial;
word-spacing: initial;
line-height: initial;
text-transform: initial;
text-indent: initial;
text-shadow: initial;
appearance: auto;
}
input:not([type=image i], [type=range i], [type=checkbox i], [type=radio i]) {
overflow: clip !important;
overflow-clip-margin: 0 !important;
}
input, select, textarea {
text-align: initial;
}
:autofill {
field-sizing: fixed !important;
}
input:is([type=reset i], [type=button i], [type=submit i]), button {
text-align: center;
}
input, button {
display: inline-block;
}
input[type=hidden i], input[type=file i], input[type=image i] {
appearance: none;
}
input:is([type=radio i], [type=checkbox i], [type=reset i], [type=button i],
[type=submit i], [type=color i], [type=search i]), select, button {
box-sizing: border-box;
}
textarea { white-space: pre-wrap; }
/* https://html.spec.whatwg.org/multipage/rendering.html#the-hr-element-2
- Omit presentational hints
*/
hr {
color: gray;
border-style: inset;
border-width: 1px;
margin-block: 0.5em;
margin-inline: auto;
overflow: hidden;
}
/* https://html.spec.whatwg.org/multipage/rendering.html#the-fieldset-and-legend-elements */
fieldset {
display: block;
margin-inline: 2px;
border: groove 2px ThreeDFace;
padding-block: 0.35em 0.625em;
padding-inline: 0.75em;
min-inline-size: min-content;
}
legend {
padding-inline: 2px;
}
legend[align=left i] {
justify-self: left;
}
legend[align=center i] {
justify-self: center;
}
legend[align=right i] {
justify-self: right;
}
/* https://html.spec.whatwg.org/multipage/rendering.html#embedded-content-rendering-rules */
iframe { border: 2px inset; }
video { object-fit: contain; }
/* https://html.spec.whatwg.org/multipage/rendering.html#images-3
- Omit quirks mode
*/
img:is([sizes="auto" i], [sizes^="auto," i]) {
contain: size !important;
contain-intrinsic-size: 300px 150px;
}
/* https://html.spec.whatwg.org/multipage/rendering.html#the-details-and-summary-elements
- Omit internal shadow tree styles
*/
details, summary {
display: block;
}
details > summary:first-of-type {
display: list-item;
counter-increment: list-item 0;
list-style: disclosure-closed inside;
}
details[open] > summary:first-of-type {
list-style-type: disclosure-open;
}
/* https://html.spec.whatwg.org/multipage/rendering.html#the-marquee-element-2 */
marquee {
display: inline-block;
text-align: initial;
overflow: hidden !important;
}
/* https://html.spec.whatwg.org/multipage/rendering.html#the-meter-element-2 */
meter { appearance: auto; }
/* https://html.spec.whatwg.org/multipage/rendering.html#the-progress-element-2 */
progress { appearance: auto; }
/* https://html.spec.whatwg.org/multipage/rendering.html#hidden-elements
- Moved to the bottom because our lack of specificity support causes tag name `display: block` and the below [hidden]
`display: none` to be last-one-wins.
*/
area, base, basefont, datalist, head, link, meta, noembed,
noframes, param, rp, script, style, template, title {
display: none;
}
[hidden]:not([hidden=until-found i]):not(embed) {
display: none;
}
[hidden=until-found i]:not(embed) {
content-visibility: hidden;
}
embed[hidden] { display: inline; height: 0; width: 0; }
input[type=hidden i] { display: none !important; }
@media (scripting) {
noscript { display: none !important; }
}

332
node_modules/jsdom/lib/jsdom/browser/js-globals.json generated vendored Normal file
View File

@@ -0,0 +1,332 @@
{
"Object": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Function": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Array": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Number": {
"writable": true,
"enumerable": false,
"configurable": true
},
"parseFloat": {
"writable": true,
"enumerable": false,
"configurable": true
},
"parseInt": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Infinity": {
"writable": false,
"enumerable": false,
"configurable": false
},
"NaN": {
"writable": false,
"enumerable": false,
"configurable": false
},
"undefined": {
"writable": false,
"enumerable": false,
"configurable": false
},
"Boolean": {
"writable": true,
"enumerable": false,
"configurable": true
},
"String": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Symbol": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Date": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Promise": {
"writable": true,
"enumerable": false,
"configurable": true
},
"RegExp": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Error": {
"writable": true,
"enumerable": false,
"configurable": true
},
"AggregateError": {
"writable": true,
"enumerable": false,
"configurable": true
},
"EvalError": {
"writable": true,
"enumerable": false,
"configurable": true
},
"RangeError": {
"writable": true,
"enumerable": false,
"configurable": true
},
"ReferenceError": {
"writable": true,
"enumerable": false,
"configurable": true
},
"SyntaxError": {
"writable": true,
"enumerable": false,
"configurable": true
},
"TypeError": {
"writable": true,
"enumerable": false,
"configurable": true
},
"URIError": {
"writable": true,
"enumerable": false,
"configurable": true
},
"globalThis": {
"writable": true,
"enumerable": false,
"configurable": true
},
"JSON": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Math": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Intl": {
"writable": true,
"enumerable": false,
"configurable": true
},
"ArrayBuffer": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Atomics": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Uint8Array": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Int8Array": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Uint16Array": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Int16Array": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Uint32Array": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Int32Array": {
"writable": true,
"enumerable": false,
"configurable": true
},
"BigUint64Array": {
"writable": true,
"enumerable": false,
"configurable": true
},
"BigInt64Array": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Uint8ClampedArray": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Float32Array": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Float64Array": {
"writable": true,
"enumerable": false,
"configurable": true
},
"DataView": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Map": {
"writable": true,
"enumerable": false,
"configurable": true
},
"BigInt": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Set": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Iterator": {
"writable": true,
"enumerable": false,
"configurable": true
},
"WeakMap": {
"writable": true,
"enumerable": false,
"configurable": true
},
"WeakSet": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Proxy": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Reflect": {
"writable": true,
"enumerable": false,
"configurable": true
},
"FinalizationRegistry": {
"writable": true,
"enumerable": false,
"configurable": true
},
"WeakRef": {
"writable": true,
"enumerable": false,
"configurable": true
},
"decodeURI": {
"writable": true,
"enumerable": false,
"configurable": true
},
"decodeURIComponent": {
"writable": true,
"enumerable": false,
"configurable": true
},
"encodeURI": {
"writable": true,
"enumerable": false,
"configurable": true
},
"encodeURIComponent": {
"writable": true,
"enumerable": false,
"configurable": true
},
"escape": {
"writable": true,
"enumerable": false,
"configurable": true
},
"unescape": {
"writable": true,
"enumerable": false,
"configurable": true
},
"eval": {
"writable": true,
"enumerable": false,
"configurable": true
},
"isFinite": {
"writable": true,
"enumerable": false,
"configurable": true
},
"isNaN": {
"writable": true,
"enumerable": false,
"configurable": true
},
"SuppressedError": {
"writable": true,
"enumerable": false,
"configurable": true
},
"DisposableStack": {
"writable": true,
"enumerable": false,
"configurable": true
},
"AsyncDisposableStack": {
"writable": true,
"enumerable": false,
"configurable": true
},
"Float16Array": {
"writable": true,
"enumerable": false,
"configurable": true
},
"SharedArrayBuffer": {
"writable": true,
"enumerable": false,
"configurable": true
},
"WebAssembly": {
"writable": true,
"enumerable": false,
"configurable": true
}
}

View File

@@ -0,0 +1,20 @@
"use strict";
exports.notImplementedMethod = (window, className, methodName, specialCircumstances) => {
exports.notImplemented(
window,
`${className}'s ${methodName}() method${specialCircumstances ? `: ${specialCircumstances}` : ""}`
);
};
exports.notImplemented = (window, message) => {
if (!window) {
// Do nothing for window-less documents.
return;
}
const error = new Error(`Not implemented: ${message}`);
error.type = "not-implemented";
window._virtualConsole.emit("jsdomError", error);
};

208
node_modules/jsdom/lib/jsdom/browser/parser/html.js generated vendored Normal file
View File

@@ -0,0 +1,208 @@
"use strict";
const parse5 = require("parse5");
const { createElement } = require("../../living/helpers/create-element");
const { HTML_NS } = require("../../living/helpers/namespaces");
const DocumentType = require("../../living/generated/DocumentType");
const DocumentFragment = require("../../living/generated/DocumentFragment");
const Text = require("../../living/generated/Text");
const Comment = require("../../living/generated/Comment");
const attributes = require("../../living/attributes");
const nodeTypes = require("../../living/node-type");
const serializationAdapter = require("../../living/domparsing/parse5-adapter-serialization");
const {
customElementReactionsStack, invokeCEReactions, lookupCEDefinition
} = require("../../living/helpers/custom-elements");
class JSDOMParse5Adapter {
constructor(documentImpl, options = {}) {
this._documentImpl = documentImpl;
this._globalObject = documentImpl._globalObject;
this._fragment = options.fragment || false;
// Since the createElement hook doesn't provide the parent element, we keep track of this using _currentElement:
// https://github.com/inikulin/parse5/issues/285.
this._currentElement = undefined;
}
_ownerDocument() {
const { _currentElement } = this;
// The _currentElement is undefined when parsing elements at the root of the document.
if (_currentElement) {
return _currentElement.localName === "template" && _currentElement.namespaceURI === HTML_NS ?
_currentElement.content._ownerDocument :
_currentElement._ownerDocument;
}
return this._documentImpl;
}
createDocument() {
// parse5's model assumes that parse(html) will call into here to create the new Document, then return it. However,
// jsdom's model assumes we can create a Window (and through that create an empty Document), do some other setup
// stuff, and then parse, stuffing nodes into that Document as we go. So to adapt between these two models, we just
// return the already-created Document when asked by parse5 to "create" a Document.
return this._documentImpl;
}
createDocumentFragment() {
const ownerDocument = this._ownerDocument();
return DocumentFragment.createImpl(this._globalObject, [], { ownerDocument });
}
// https://html.spec.whatwg.org/#create-an-element-for-the-token
createElement(localName, namespace, attrs) {
const ownerDocument = this._ownerDocument();
const isAttribute = attrs.find(attr => attr.name === "is");
const isValue = isAttribute ? isAttribute.value : null;
const definition = lookupCEDefinition(ownerDocument, namespace, localName);
let willExecuteScript = false;
if (definition !== null && !this._fragment) {
willExecuteScript = true;
}
if (willExecuteScript) {
ownerDocument._throwOnDynamicMarkupInsertionCounter++;
customElementReactionsStack.push([]);
}
const element = createElement(ownerDocument, localName, namespace, null, isValue, willExecuteScript);
this.adoptAttributes(element, attrs);
if (willExecuteScript) {
const queue = customElementReactionsStack.pop();
invokeCEReactions(queue);
ownerDocument._throwOnDynamicMarkupInsertionCounter--;
}
if ("_parserInserted" in element) {
element._parserInserted = true;
}
return element;
}
createCommentNode(data) {
const ownerDocument = this._ownerDocument();
return Comment.createImpl(this._globalObject, [], { data, ownerDocument });
}
appendChild(parentNode, newNode) {
parentNode._append(newNode);
}
insertBefore(parentNode, newNode, referenceNode) {
parentNode._insert(newNode, referenceNode);
}
setTemplateContent(templateElement, contentFragment) {
// This code makes the glue between jsdom and parse5 HTMLTemplateElement parsing:
//
// * jsdom during the construction of the HTMLTemplateElement (for example when create via
// `document.createElement("template")`), creates a DocumentFragment and set it into _templateContents.
// * parse5 when parsing a <template> tag creates an HTMLTemplateElement (`createElement` adapter hook) and also
// create a DocumentFragment (`createDocumentFragment` adapter hook).
//
// At this point we now have to replace the one created in jsdom with one created by parse5.
const { _ownerDocument, _host } = templateElement._templateContents;
contentFragment._ownerDocument = _ownerDocument;
contentFragment._host = _host;
templateElement._templateContents = contentFragment;
}
setDocumentType(document, name, publicId, systemId) {
const ownerDocument = this._ownerDocument();
const documentType = DocumentType.createImpl(this._globalObject, [], { name, publicId, systemId, ownerDocument });
document._append(documentType);
}
setDocumentMode(document, mode) {
// TODO: the rest of jsdom ignores this
document._mode = mode;
}
detachNode(node) {
node.remove();
}
insertText(parentNode, text) {
const { lastChild } = parentNode;
if (lastChild && lastChild.nodeType === nodeTypes.TEXT_NODE) {
lastChild.data += text;
} else {
const ownerDocument = this._ownerDocument();
const textNode = Text.createImpl(this._globalObject, [], { data: text, ownerDocument });
parentNode._append(textNode);
}
}
insertTextBefore(parentNode, text, referenceNode) {
const { previousSibling } = referenceNode;
if (previousSibling && previousSibling.nodeType === nodeTypes.TEXT_NODE) {
previousSibling.data += text;
} else {
const ownerDocument = this._ownerDocument();
const textNode = Text.createImpl(this._globalObject, [], { data: text, ownerDocument });
parentNode._append(textNode, referenceNode);
}
}
adoptAttributes(element, attrs) {
for (const attr of attrs) {
const prefix = attr.prefix === "" ? null : attr.prefix;
attributes.setAttributeValue(element, attr.name, attr.value, prefix, attr.namespace);
}
}
onItemPush(after) {
this._currentElement = after;
after._pushedOnStackOfOpenElements?.();
}
onItemPop(before, newTop) {
this._currentElement = newTop;
before._poppedOffStackOfOpenElements?.();
}
}
// Assign shared adapters with serializer.
Object.assign(JSDOMParse5Adapter.prototype, serializationAdapter);
function parseFragment(markup, contextElement) {
const ownerDocument = contextElement.localName === "template" && contextElement.namespaceURI === HTML_NS ?
contextElement.content._ownerDocument :
contextElement._ownerDocument;
const config = {
...ownerDocument._parseOptions,
sourceCodeLocationInfo: false,
treeAdapter: new JSDOMParse5Adapter(ownerDocument, { fragment: true })
};
return parse5.parseFragment(contextElement, markup, config);
}
function parseIntoDocument(markup, ownerDocument) {
const config = {
...ownerDocument._parseOptions,
treeAdapter: new JSDOMParse5Adapter(ownerDocument)
};
return parse5.parse(markup, config);
}
module.exports = {
parseFragment,
parseIntoDocument
};

37
node_modules/jsdom/lib/jsdom/browser/parser/index.js generated vendored Normal file
View File

@@ -0,0 +1,37 @@
"use strict";
const xmlParser = require("./xml");
const htmlParser = require("./html");
// https://w3c.github.io/DOM-Parsing/#dfn-fragment-parsing-algorithm
function parseFragment(markup, contextElement) {
const { _parsingMode } = contextElement._ownerDocument;
let parseAlgorithm;
if (_parsingMode === "html") {
parseAlgorithm = htmlParser.parseFragment;
} else if (_parsingMode === "xml") {
parseAlgorithm = xmlParser.parseFragment;
}
// Note: HTML and XML fragment parsing algorithm already return a document fragments; no need to do steps 3 and 4
return parseAlgorithm(markup, contextElement);
}
function parseIntoDocument(markup, ownerDocument) {
const { _parsingMode } = ownerDocument;
let parseAlgorithm;
if (_parsingMode === "html") {
parseAlgorithm = htmlParser.parseIntoDocument;
} else if (_parsingMode === "xml") {
parseAlgorithm = xmlParser.parseIntoDocument;
}
return parseAlgorithm(markup, ownerDocument);
}
module.exports = {
parseFragment,
parseIntoDocument
};

202
node_modules/jsdom/lib/jsdom/browser/parser/xml.js generated vendored Normal file
View File

@@ -0,0 +1,202 @@
"use strict";
const { SaxesParser } = require("saxes");
const DOMException = require("../../living/generated/DOMException");
const { createElement } = require("../../living/helpers/create-element");
const DocumentFragment = require("../../living/generated/DocumentFragment");
const DocumentType = require("../../living/generated/DocumentType");
const CDATASection = require("../../living/generated/CDATASection");
const Comment = require("../../living/generated/Comment");
const ProcessingInstruction = require("../../living/generated/ProcessingInstruction");
const Text = require("../../living/generated/Text");
const attributes = require("../../living/attributes");
const { HTML_NS } = require("../../living/helpers/namespaces");
const HTML5_DOCTYPE = /<!doctype html>/i;
const PUBLIC_DOCTYPE = /<!doctype\s+([^\s]+)\s+public\s+"([^"]+)"\s+"([^"]+)"/i;
const SYSTEM_DOCTYPE = /<!doctype\s+([^\s]+)\s+system\s+"([^"]+)"/i;
const CUSTOM_NAME_DOCTYPE = /<!doctype\s+([^\s>]+)/i;
function parseDocType(globalObject, ownerDocument, html) {
if (HTML5_DOCTYPE.test(html)) {
return createDocumentType(globalObject, ownerDocument, "html", "", "");
}
const publicPieces = PUBLIC_DOCTYPE.exec(html);
if (publicPieces) {
return createDocumentType(globalObject, ownerDocument, publicPieces[1], publicPieces[2], publicPieces[3]);
}
const systemPieces = SYSTEM_DOCTYPE.exec(html);
if (systemPieces) {
return createDocumentType(globalObject, ownerDocument, systemPieces[1], "", systemPieces[2]);
}
const namePiece = CUSTOM_NAME_DOCTYPE.exec(html)[1] || "html";
return createDocumentType(globalObject, ownerDocument, namePiece, "", "");
}
function createDocumentType(globalObject, ownerDocument, name, publicId, systemId) {
return DocumentType.createImpl(globalObject, [], { ownerDocument, name, publicId, systemId });
}
function isHTMLTemplateElement(element) {
return element.tagName === "template" && element.namespaceURI === HTML_NS;
}
function createParser(rootNode, globalObject, saxesOptions) {
const parser = new SaxesParser({
...saxesOptions,
// Browsers always have namespace support.
xmlns: true,
// We force the parser to treat all documents (even documents declaring themselves to be XML 1.1 documents) as XML
// 1.0 documents. See https://github.com/jsdom/jsdom/issues/2677 for a discussion of the stakes.
defaultXMLVersion: "1.0",
forceXMLVersion: true
});
const openStack = [rootNode];
function getOwnerDocument() {
const currentElement = openStack[openStack.length - 1];
return isHTMLTemplateElement(currentElement) ?
currentElement._templateContents._ownerDocument :
currentElement._ownerDocument;
}
function appendChild(child) {
const parentElement = openStack[openStack.length - 1];
if (isHTMLTemplateElement(parentElement)) {
parentElement._templateContents._insert(child, null);
} else {
parentElement._insert(child, null);
}
}
parser.on("text", saxesOptions.fragment ?
// In a fragment, all text events produced by saxes must result in a text
// node.
data => {
const ownerDocument = getOwnerDocument();
appendChild(Text.createImpl(globalObject, [], { data, ownerDocument }));
} :
// When parsing a whole document, we must ignore those text nodes that are
// produced outside the root element. Saxes produces events for them,
// but DOM trees do not record text outside the root element.
data => {
if (openStack.length > 1) {
const ownerDocument = getOwnerDocument();
appendChild(Text.createImpl(globalObject, [], { data, ownerDocument }));
}
});
parser.on("cdata", data => {
const ownerDocument = getOwnerDocument();
appendChild(CDATASection.createImpl(globalObject, [], { data, ownerDocument }));
});
parser.on("opentag", tag => {
const { local: tagLocal, attributes: tagAttributes } = tag;
const ownerDocument = getOwnerDocument();
const tagNamespace = tag.uri === "" ? null : tag.uri;
const tagPrefix = tag.prefix === "" ? null : tag.prefix;
const isValue = tagAttributes.is === undefined ? null : tagAttributes.is.value;
const elem = createElement(ownerDocument, tagLocal, tagNamespace, tagPrefix, isValue, true);
// We mark a script element as "parser-inserted", which prevents it from
// being immediately executed.
if (tagLocal === "script" && tagNamespace === HTML_NS) {
elem._parserInserted = true;
}
for (const key of Object.keys(tagAttributes)) {
const { prefix, local, uri, value } = tagAttributes[key];
attributes.setAttributeValue(elem, local, value, prefix === "" ? null : prefix, uri === "" ? null : uri);
}
appendChild(elem);
openStack.push(elem);
});
parser.on("closetag", () => {
const elem = openStack.pop();
// Once a script is populated, we can execute it.
if (elem.localName === "script" && elem.namespaceURI === HTML_NS) {
elem._eval();
}
});
parser.on("comment", data => {
const ownerDocument = getOwnerDocument();
appendChild(Comment.createImpl(globalObject, [], { data, ownerDocument }));
});
parser.on("processinginstruction", ({ target, body }) => {
const ownerDocument = getOwnerDocument();
appendChild(ProcessingInstruction.createImpl(globalObject, [], { target, data: body, ownerDocument }));
});
parser.on("doctype", dt => {
const ownerDocument = getOwnerDocument();
appendChild(parseDocType(globalObject, ownerDocument, `<!doctype ${dt}>`));
const entityMatcher = /<!ENTITY ([^ ]+) "([^"]+)">/g;
let result;
while ((result = entityMatcher.exec(dt))) {
const [, name, value] = result;
if (!(name in parser.ENTITIES)) {
parser.ENTITIES[name] = value;
}
}
});
parser.on("error", err => {
throw DOMException.create(globalObject, [err.message, "SyntaxError"]);
});
return parser;
}
function parseFragment(markup, contextElement) {
const { _globalObject, _ownerDocument } = contextElement;
const fragment = DocumentFragment.createImpl(_globalObject, [], { ownerDocument: _ownerDocument });
// Only parseFragment needs resolvePrefix per the saxes documentation:
// https://github.com/lddubeau/saxes#parsing-xml-fragments
const parser = createParser(fragment, _globalObject, {
fragment: true,
resolvePrefix(prefix) {
// saxes wants undefined as the return value if the prefix is not defined, not null.
return contextElement.lookupNamespaceURI(prefix) || undefined;
}
});
parser.write(markup).close();
return fragment;
}
function parseIntoDocument(markup, ownerDocument) {
const { _globalObject } = ownerDocument;
const parser = createParser(ownerDocument, _globalObject, {
fileName: ownerDocument.location && ownerDocument.location.href
});
parser.write(markup).close();
return ownerDocument;
}
module.exports = {
parseFragment,
parseIntoDocument
};

View File

@@ -0,0 +1,114 @@
"use strict";
class QueueItem {
constructor(onLoad, onError, dependentItem) {
this.onLoad = onLoad;
this.onError = onError;
this.data = null;
this.error = null;
this.dependentItem = dependentItem;
}
}
/**
* AsyncResourceQueue is the queue in charge of run the async scripts
* and notify when they finish.
*/
module.exports = class AsyncResourceQueue {
constructor() {
this.items = new Set();
this.dependentItems = new Set();
}
count() {
return this.items.size + this.dependentItems.size;
}
_notify() {
if (this._listener) {
this._listener();
}
}
_check(item) {
let promise;
if (item.onError && item.error) {
promise = item.onError(item.error);
} else if (item.onLoad && item.data) {
promise = item.onLoad(item.data);
}
promise
.then(() => {
this.items.delete(item);
this.dependentItems.delete(item);
if (this.count() === 0) {
this._notify();
}
});
}
setListener(listener) {
this._listener = listener;
}
push(request, onLoad, onError, dependentItem) {
const q = this;
const item = new QueueItem(onLoad, onError, dependentItem);
q.items.add(item);
return request
.then(data => {
item.data = data;
if (dependentItem && !dependentItem.finished) {
q.dependentItems.add(item);
return q.items.delete(item);
}
if (onLoad) {
return q._check(item);
}
q.items.delete(item);
if (q.count() === 0) {
q._notify();
}
return null;
})
.catch(err => {
item.error = err;
if (dependentItem && !dependentItem.finished) {
q.dependentItems.add(item);
return q.items.delete(item);
}
if (onError) {
return q._check(item);
}
q.items.delete(item);
if (q.count() === 0) {
q._notify();
}
return null;
});
}
notifyItem(syncItem) {
for (const item of this.dependentItems) {
if (item.dependentItem === syncItem) {
this._check(item);
}
}
}
};

View File

@@ -0,0 +1,184 @@
"use strict";
// Adapted from undici's lib/interceptor/decompress.js
// https://github.com/nodejs/undici/blob/main/lib/interceptor/decompress.js
// Changes:
// - Removed zstd support (requires runtimeFeatures check)
// - Removed experimental warning
// - Use undici's exported DecoratorHandler
const { createInflate, createGunzip, createBrotliDecompress } = require("zlib");
const { pipeline } = require("stream");
const { DecoratorHandler } = require("undici");
const supportedEncodings = {
"gzip": createGunzip,
"x-gzip": createGunzip,
"br": createBrotliDecompress,
"deflate": createInflate,
"compress": createInflate,
"x-compress": createInflate
};
const defaultSkipStatusCodes = [204, 304];
class DecompressHandler extends DecoratorHandler {
#decompressors = [];
#skipStatusCodes;
#skipErrorResponses;
constructor(handler, { skipStatusCodes = defaultSkipStatusCodes, skipErrorResponses = true } = {}) {
super(handler);
this.#skipStatusCodes = skipStatusCodes;
this.#skipErrorResponses = skipErrorResponses;
}
#shouldSkipDecompression(contentEncoding, statusCode) {
if (!contentEncoding || statusCode < 200) {
return true;
}
if (this.#skipStatusCodes.includes(statusCode)) {
return true;
}
if (this.#skipErrorResponses && statusCode >= 400) {
return true;
}
return false;
}
#createDecompressionChain(encodings) {
const parts = encodings.split(",");
const maxContentEncodings = 5;
if (parts.length > maxContentEncodings) {
throw new Error(`too many content-encodings in response: ${parts.length}, max is ${maxContentEncodings}`);
}
const decompressors = [];
for (let i = parts.length - 1; i >= 0; i--) {
const encoding = parts[i].trim();
if (!encoding) {
continue;
}
if (!supportedEncodings[encoding]) {
decompressors.length = 0;
return decompressors;
}
decompressors.push(supportedEncodings[encoding]());
}
return decompressors;
}
#setupDecompressorEvents(decompressor, controller) {
decompressor.on("readable", () => {
let chunk;
while ((chunk = decompressor.read()) !== null) {
const result = super.onResponseData(controller, chunk);
if (result === false) {
break;
}
}
});
decompressor.on("error", error => {
super.onResponseError(controller, error);
});
}
#setupSingleDecompressor(controller) {
const decompressor = this.#decompressors[0];
this.#setupDecompressorEvents(decompressor, controller);
decompressor.on("end", () => {
super.onResponseEnd(controller, {});
});
}
#setupMultipleDecompressors(controller) {
const lastDecompressor = this.#decompressors[this.#decompressors.length - 1];
this.#setupDecompressorEvents(lastDecompressor, controller);
pipeline(this.#decompressors, err => {
if (err) {
super.onResponseError(controller, err);
return;
}
super.onResponseEnd(controller, {});
});
}
#cleanupDecompressors() {
this.#decompressors.length = 0;
}
onResponseStart(controller, statusCode, headers, statusMessage) {
const contentEncoding = headers["content-encoding"];
if (this.#shouldSkipDecompression(contentEncoding, statusCode)) {
return super.onResponseStart(controller, statusCode, headers, statusMessage);
}
const decompressors = this.#createDecompressionChain(contentEncoding.toLowerCase());
if (decompressors.length === 0) {
this.#cleanupDecompressors();
return super.onResponseStart(controller, statusCode, headers, statusMessage);
}
this.#decompressors = decompressors;
// Keep content-encoding and content-length headers as-is
// XHR spec requires these to reflect the wire format, not the decoded body
const newHeaders = { ...headers };
if (this.#decompressors.length === 1) {
this.#setupSingleDecompressor(controller);
} else {
this.#setupMultipleDecompressors(controller);
}
return super.onResponseStart(controller, statusCode, newHeaders, statusMessage);
}
onResponseData(controller, chunk) {
if (this.#decompressors.length > 0) {
this.#decompressors[0].write(chunk);
return;
}
super.onResponseData(controller, chunk);
}
onResponseEnd(controller, trailers) {
if (this.#decompressors.length > 0) {
this.#decompressors[0].end();
this.#cleanupDecompressors();
return;
}
super.onResponseEnd(controller, trailers);
}
onResponseError(controller, err) {
if (this.#decompressors.length > 0) {
for (const decompressor of this.#decompressors) {
decompressor.destroy(err);
}
this.#cleanupDecompressors();
}
super.onResponseError(controller, err);
}
}
function createDecompressInterceptor(options = {}) {
return dispatch => {
return (opts, handler) => {
const decompressHandler = new DecompressHandler(handler, options);
return dispatch(opts, decompressHandler);
};
};
}
module.exports = createDecompressInterceptor;

View File

@@ -0,0 +1,746 @@
"use strict";
const fs = require("fs");
const { Readable } = require("stream");
const { fileURLToPath } = require("url");
const { parseURL, serializeURL, serializeURLOrigin, serializePath } = require("whatwg-url");
const dataURLFromRecord = require("data-urls").fromURLRecord;
const { Dispatcher } = require("undici");
const WrapHandler = require("undici/lib/handler/wrap-handler.js");
const { toBase64 } = require("@exodus/bytes/base64.js");
const { utf8Encode } = require("../../living/helpers/encoding");
const { sendStreamResponse } = require("./stream-handler");
const packageVersion = require("../../../../package.json").version;
const DEFAULT_USER_AGENT = `Mozilla/5.0 (${process.platform || "unknown OS"}) AppleWebKit/537.36 ` +
`(KHTML, like Gecko) jsdom/${packageVersion}`;
const MAX_REDIRECTS = 20;
/**
* JSDOMDispatcher - Full undici Dispatcher implementation for jsdom.
*
* Handles:
* - data: URLs (decode and return)
* - file: URLs (read from filesystem)
* - HTTP(S) and web sockets: follows redirects manually, capturing cookies at each hop
*
* Callers should provide the expected opaque fields when possible, to ensure that various parts of the jsdom pipeline
* have enough information. See the `dispatch()` JSDoc for details.
*/
class JSDOMDispatcher extends Dispatcher {
#baseDispatcher;
#cookieJar;
#userAgent;
#userInterceptors;
constructor({ baseDispatcher, cookieJar, userAgent, userInterceptors = [] }) {
super();
this.#baseDispatcher = baseDispatcher;
this.#cookieJar = cookieJar;
this.#userAgent = userAgent || DEFAULT_USER_AGENT;
this.#userInterceptors = userInterceptors;
}
/**
* Dispatch a request through the jsdom resource loading pipeline.
*
* Vaguely corresponds to:
* - https://fetch.spec.whatwg.org/#concept-fetch: in theory, all jsdom fetches should go through here, like all web
* platform fetches go through #concept-fetch.
* - https://fetch.spec.whatwg.org/#concept-scheme-fetch: the code is more like skipping straight to scheme fetch.
*
* @param {object} opts - undici dispatch options
* @param {object} [opts.opaque] - jsdom-specific request context (may be undefined for WebSocket upgrades)
* @param {Element|null} opts.opaque.element - DOM element that triggered the request
* @param {string} opts.opaque.url - Full request URL (since we cannot reconstruct it from `opts.origin + opts.path`
* for `file:` URLs). If given, `opts.origin`, `opts.path`, and `opts.query` are ignored.
* @param {string} [opts.opaque.origin] - Request origin for CORS (used by XHR)
* @param {boolean} [opts.opaque.corsMode] - Enable CORS validation during redirects (used by XHR)
* @param {boolean} [opts.opaque.withCredentials] - Include cookies cross-origin (used by XHR)
* @param {Object} [opts.opaque.auth] - Auth credentials {user, pass} for 401 Basic auth handling
* @param {Object} [opts.opaque.preflight] - If present, do CORS preflight before main request
* @param {string[]} [opts.opaque.preflight.unsafeHeaders] - Non-simple headers that need to be allowed
* @param {object} handler - undici handler
*/
dispatch(opts, handler) {
// Wrap handler to normalize OLD API (onConnect/onHeaders/onData/onComplete/onError) to NEW API
// (onRequestStart/onResponseStart/onResponseData/onResponseEnd/onResponseError). This is necessary because undici's
// internals call the old API a lot, despite it being undocumented:
// * https://github.com/nodejs/undici/issues/4771
// * https://github.com/nodejs/undici/issues/4780
const wrappedHandler = WrapHandler.wrap(handler);
// Get URL from opaque if present (required for file: URLs since they have origin "null"),
// otherwise reconstruct from opts.origin + opts.path (works for http/https/ws/wss)
const urlString = opts.opaque?.url || (opts.origin + opts.path);
const urlRecord = parseURL(urlString);
if (urlRecord === null) {
wrappedHandler.onResponseError?.(null, new TypeError(`Invalid URL: ${urlString}`));
return false;
}
if (urlRecord.scheme === "data") {
return this.#dispatchDataURL(urlRecord, wrappedHandler);
}
if (urlRecord.scheme === "file") {
return this.#dispatchFileURL(urlRecord, wrappedHandler);
}
// HTTP(S) - handles redirects, CORS, preflight, and WebSocket upgrades
this.#dispatchHTTP(urlRecord, wrappedHandler, opts);
return true;
}
/**
* Handle `data:` URLs by decoding them and returning the body.
*
* Corresponds fairly directly to https://fetch.spec.whatwg.org/#concept-scheme-fetch's "data" scheme case.
*/
#dispatchDataURL(urlRecord, handler) {
const dataURL = dataURLFromRecord(urlRecord);
if (dataURL === null) {
const error = new TypeError("Invalid data: URL");
handler.onResponseError?.(null, error);
return false;
}
const stream = Readable.from([dataURL.body]);
sendStreamResponse(handler, stream, {
status: 200,
statusText: "OK",
headers: { "content-type": dataURL.mimeType.toString() },
context: { finalURL: urlRecord }
});
return true;
}
/**
* Handle `file:` URLs by reading from the filesystem.
*
* Corresponds fairly directly to https://fetch.spec.whatwg.org/#concept-scheme-fetch's "file" scheme case.
*/
#dispatchFileURL(urlRecord, handler) {
const filePath = fileURLToPath(serializeURL(urlRecord));
const stream = fs.createReadStream(filePath);
sendStreamResponse(handler, stream, {
status: 200,
statusText: "OK",
context: { finalURL: urlRecord }
});
return true;
}
/**
* High-level HTTP(S) fetch with redirect handling, CORS validation, and preflight.
*
* Corresponds roughly to https://fetch.spec.whatwg.org/#concept-http-fetch, although some parts of
* https://fetch.spec.whatwg.org/#concept-fetch also live here.
*/
async #dispatchHTTP(urlRecord, handler, opts) {
const { corsMode, origin, withCredentials, auth, preflight } = opts.opaque || {};
const requestFragment = urlRecord.fragment;
let currentURL = urlRecord;
let currentMethod = opts.method || "GET";
let currentBody = opts.body ?? null;
const currentHeaders = { ...this.#normalizeHeadersToObject(opts.headers) };
let effectiveOrigin = origin; // CORS tracking - may become "null" after cross-origin redirects
let receivedAuthChallenge = false;
const ctx = { finalURL: null };
// Create a proxy controller that forwards to the current underlying controller.
// This provides a stable reference across redirect hops.
let currentController;
let onRequestStartCalled = false;
const proxyController = {
abort(reason) {
currentController.abort(reason);
},
pause() {
currentController.pause();
},
resume() {
currentController.resume();
},
get paused() {
return currentController.paused;
},
get aborted() {
return currentController.aborted;
},
get reason() {
return currentController.reason;
}
};
// Callback for #doSingleRequest to invoke when a controller becomes available
function onControllerReady(controller) {
currentController = controller;
if (!onRequestStartCalled) {
onRequestStartCalled = true;
handler.onRequestStart?.(proxyController, ctx);
}
}
// Handle CORS preflight if needed
if (preflight) {
const preflightHeaders = {
Origin: origin
};
preflightHeaders["Access-Control-Request-Method"] = currentMethod;
if (preflight.unsafeHeaders?.length > 0) {
preflightHeaders["Access-Control-Request-Headers"] = preflight.unsafeHeaders.join(", ");
}
const preflightResult = await this.#doSingleRequest(
currentURL,
"OPTIONS",
preflightHeaders,
null,
{ ...opts.opaque, origin, withCredentials },
undefined, // no upgrade for preflight
opts,
onControllerReady
);
if (preflightResult.error) {
handler.onResponseError?.(null, preflightResult.error);
return;
}
// Validate preflight response status
if (preflightResult.status < 200 || preflightResult.status > 299) {
handler.onResponseError?.(null, new Error(
"Response for preflight has invalid HTTP status code " + preflightResult.status
));
return;
}
// CORS validation on preflight response
const acao = preflightResult.headers["access-control-allow-origin"];
if (acao !== "*" && acao !== origin) {
handler.onResponseError?.(null, new Error("Cross origin " + origin + " forbidden"));
return;
}
if (withCredentials) {
const acac = preflightResult.headers["access-control-allow-credentials"];
if (acac !== "true") {
handler.onResponseError?.(null, new Error("Credentials forbidden"));
return;
}
}
// Validate allowed headers
const acahStr = preflightResult.headers["access-control-allow-headers"];
const acah = new Set(acahStr ? acahStr.toLowerCase().split(/,\s*/) : []);
if (!acah.has("*")) {
for (const unsafeHeader of preflight.unsafeHeaders || []) {
if (!acah.has(unsafeHeader.toLowerCase())) {
handler.onResponseError?.(null, new Error("Header " + unsafeHeader + " forbidden"));
return;
}
}
}
}
// Redirect loop
for (let redirectCount = 0; redirectCount <= MAX_REDIRECTS; redirectCount++) {
ctx.finalURL = currentURL;
const currentOrigin = serializeURLOrigin(currentURL);
// Clone headers for this request
const requestHeaders = { ...currentHeaders };
// Add auth header if needed
if (receivedAuthChallenge && auth) {
const authString = `${auth.user || ""}:${auth.pass || ""}`;
requestHeaders.Authorization = "Basic " + toBase64(utf8Encode(authString));
}
const result = await this.#doSingleRequest(
currentURL,
currentMethod,
requestHeaders,
currentBody,
{ ...opts.opaque, origin, withCredentials },
opts.upgrade,
opts,
onControllerReady
);
// WebSocket upgrade
if (result.upgraded) {
handler.onRequestUpgrade?.(proxyController, result.statusCode, result.headers, result.socket);
return;
}
if (result.error) {
handler.onResponseError?.(null, result.error);
return;
}
// Handle 401 auth challenge
if (result.status === 401 && auth && !receivedAuthChallenge) {
const wwwAuth = result.headers["www-authenticate"] || "";
if (/^Basic /i.test(wwwAuth)) {
receivedAuthChallenge = true;
continue;
}
}
// Handle redirect
const { location } = result.headers;
if (result.status >= 300 && result.status < 400 && location) {
const targetURL = parseURL(location, { baseURL: currentURL });
if (!targetURL) {
handler.onResponseError?.(null, new TypeError("Invalid redirect URL"));
return;
}
// Per fetch spec: if location's fragment is null, inherit from request
if (targetURL.fragment === null) {
targetURL.fragment = requestFragment;
}
// Per fetch spec: if locationURL's scheme is not HTTP(S), return a network error
if (targetURL.scheme !== "http" && targetURL.scheme !== "https") {
handler.onResponseError?.(null, new Error("Cannot redirect to non-HTTP(S) URL"));
return;
}
// Method change per fetch spec "HTTP-redirect fetch"
// 301/302 + POST → GET, 303 + non-GET/HEAD → GET
if (((result.status === 301 || result.status === 302) && currentMethod === "POST") ||
(result.status === 303 && !["GET", "HEAD"].includes(currentMethod))) {
currentMethod = "GET";
currentBody = null;
this.#deleteRequestHeader(currentHeaders, "content-encoding");
this.#deleteRequestHeader(currentHeaders, "content-language");
this.#deleteRequestHeader(currentHeaders, "content-location");
this.#deleteRequestHeader(currentHeaders, "content-type");
}
const targetOrigin = serializeURLOrigin(targetURL);
// Authorization header removal on cross-origin redirect
if (currentOrigin !== targetOrigin) {
this.#deleteRequestHeader(currentHeaders, "authorization");
}
// CORS handling for cross-origin redirects (only if origin is set, indicating XHR/fetch)
const targetIsCrossOrigin = origin !== undefined && origin !== targetOrigin;
if (corsMode || targetIsCrossOrigin) {
// CORS validation on redirect response (if source was cross-origin)
if (origin !== currentOrigin) {
const acao = result.headers["access-control-allow-origin"];
if (acao !== "*" && acao !== origin) {
handler.onResponseError?.(null, new Error("Cross origin " + origin + " forbidden"));
return;
}
if (withCredentials) {
const acac = result.headers["access-control-allow-credentials"];
if (acac !== "true") {
handler.onResponseError?.(null, new Error("Credentials forbidden"));
return;
}
}
// Userinfo check - forbid redirects to URLs with username/password
if (targetURL.username || targetURL.password) {
handler.onResponseError?.(null, new Error("Userinfo forbidden in cors redirect"));
return;
}
// Update effective origin - becomes "null" after cross-origin→cross-origin redirect
if (currentOrigin !== targetOrigin) {
effectiveOrigin = "null";
}
}
// Add Origin header for cross-origin target or if effective origin became "null"
if (targetIsCrossOrigin || effectiveOrigin === "null") {
currentHeaders.Origin = effectiveOrigin;
}
}
currentURL = targetURL;
continue;
}
// Final response - CORS validation (if destination is cross-origin or effective origin is "null")
if (origin !== undefined && (origin !== currentOrigin || effectiveOrigin === "null")) {
const acao = result.headers["access-control-allow-origin"];
if (acao !== "*" && acao !== effectiveOrigin) {
handler.onResponseError?.(null, new Error("Cross origin " + effectiveOrigin + " forbidden"));
return;
}
if (withCredentials) {
const acac = result.headers["access-control-allow-credentials"];
if (acac !== "true") {
handler.onResponseError?.(null, new Error("Credentials forbidden"));
return;
}
}
}
// Stream response to handler
handler.onResponseStart?.(proxyController, result.status, result.headers, result.statusText);
// Forward body chunks to handler
result.forwardBodyTo(handler);
return;
}
handler.onResponseError?.(null, new Error(`Too many redirects (max ${MAX_REDIRECTS})`));
}
/**
* Perform a single HTTP request (no redirects).
* Handles cookies based on cross-origin/credentials settings.
* Returns response metadata immediately, with a forwardBodyTo() method to stream the body later.
*
* For WebSocket upgrades, returns { upgraded: true, controller, statusCode, headers, socket }.
*
* Mostly corresponds to https://fetch.spec.whatwg.org/#concept-http-network-fetch.
*
* @param {object} url - URL record to request
* @param {string} method - HTTP method
* @param {object} headers - Request headers
* @param {*} body - Request body
* @param {object} opaque - jsdom opaque options
* @param {string} upgrade - Upgrade protocol (e.g., "websocket")
* @param {object} originalOpts - Original dispatch options to preserve extra undici options
* @param {function} onControllerReady - Callback invoked when controller is available
*/
async #doSingleRequest(url, method, headers, body, opaque, upgrade, originalOpts, onControllerReady) {
const { origin: requestOrigin, withCredentials } = opaque || {};
// Build headers with defaults
const requestHeaders = { ...headers };
this.#setDefaultHeaders(requestHeaders);
if (body === null && (method === "POST" || method === "PUT")) {
requestHeaders["Content-Length"] = "0";
} else if (body !== null && body.byteLength !== undefined) {
// The `body.byteLength !== undefined` check is equivalent to the spec case where httpRequest's body's length is
// null, because body is a stream.
requestHeaders["Content-Length"] = String(body.byteLength);
}
// Determine if this is cross-origin (for cookie handling)
const urlOrigin = serializeURLOrigin(url);
const crossOrigin = requestOrigin !== undefined && requestOrigin !== urlOrigin;
// Only handle cookies for same-origin requests, or cross-origin with credentials
// Don't send cookies for preflight requests
const isPreflight = method === "OPTIONS" &&
this.#hasRequestHeader(headers, "Access-Control-Request-Method");
const shouldHandleCookies = (!crossOrigin || withCredentials) && !isPreflight;
const urlSerialized = serializeURL(url);
if (shouldHandleCookies) {
const cookieString = this.#cookieJar.getCookieStringSync(urlSerialized);
if (cookieString) {
requestHeaders.Cookie = cookieString;
}
}
// Spread original opts to preserve extra undici options (e.g., idempotent, bodyTimeout),
// then override with our specific values.
// If opaque.url was provided, derive origin/path from it and null out query.
// Otherwise, pass through origin/path/query unchanged.
const hasOpaqueURL = opaque?.url !== undefined;
const dispatchOpts = {
...originalOpts,
origin: hasOpaqueURL ? urlOrigin : originalOpts.origin,
path: hasOpaqueURL ? serializePathForUndici(url) : originalOpts.path,
query: hasOpaqueURL ? null : originalOpts.query,
method,
headers: requestHeaders,
body,
upgrade,
opaque: { ...opaque, url: urlSerialized }
};
const innerDispatch = this.#buildDispatchChain();
return new Promise(resolve => {
let responseHeaders, streamError;
let bodyHandler = null;
let pendingChunks = [];
let ended = false;
let responseStarted = false;
innerDispatch(dispatchOpts, {
onRequestStart: controller => {
onControllerReady(controller);
},
onRequestUpgrade: (controller, statusCode, headersObj, socket) => {
if (controller.aborted) {
resolve({ error: controller.reason });
return;
}
if (shouldHandleCookies) {
this.#storeCookiesFromHeaders(headersObj, urlSerialized);
}
resolve({ upgraded: true, controller, statusCode, headers: headersObj, socket });
},
onResponseStart: (controller, statusCode, headersObj, statusText) => {
if (controller.aborted) {
resolve({ error: controller.reason });
return;
}
responseHeaders = headersObj;
responseStarted = true;
// Create a mechanism to forward body to handler later
function forwardBodyTo(fwdHandler) {
bodyHandler = fwdHandler;
// Forward any chunks that arrived before forwardBodyTo was called
for (const chunk of pendingChunks) {
fwdHandler.onResponseData?.(controller, chunk);
}
pendingChunks = null;
if (streamError) {
fwdHandler.onResponseError?.(controller, streamError);
} else if (ended) {
fwdHandler.onResponseEnd?.(controller, {});
}
}
resolve({
status: statusCode,
statusText: statusText || "",
headers: responseHeaders,
url,
forwardBodyTo
});
},
onResponseData: (controller, chunk) => {
if (controller.aborted) {
return;
}
if (bodyHandler) {
bodyHandler.onResponseData?.(controller, chunk);
} else {
pendingChunks.push(chunk);
}
},
onResponseEnd: (controller, trailers) => {
if (controller.aborted) {
if (bodyHandler) {
bodyHandler.onResponseError?.(controller, controller.reason);
} else {
streamError = controller.reason;
}
return;
}
if (shouldHandleCookies) {
this.#storeCookiesFromHeaders(responseHeaders, urlSerialized);
}
if (bodyHandler) {
bodyHandler.onResponseEnd?.(controller, trailers);
} else {
ended = true;
}
},
onResponseError: (controller, err) => {
if (responseStarted) {
// Error occurred mid-stream - forward to body handler
if (bodyHandler) {
bodyHandler.onResponseError?.(controller, err);
} else {
streamError = err;
}
} else {
resolve({ error: err });
}
}
});
});
}
/**
* Build the dispatch chain with user interceptors applied.
*/
#buildDispatchChain() {
let innerDispatch = (opts, h) => {
return this.#baseDispatcher.dispatch(opts, h);
};
// Apply user interceptors from innermost to outermost
for (let i = this.#userInterceptors.length - 1; i >= 0; i--) {
const interceptor = this.#userInterceptors[i];
const nextDispatch = innerDispatch;
innerDispatch = (opts, h) => interceptor(nextDispatch)(opts, h);
}
return innerDispatch;
}
/**
* Normalize headers to an object format.
* Callers pass either HeaderList (iterable) or plain objects.
*/
#normalizeHeadersToObject(headers) {
if (!headers) {
return {};
}
// HeaderList has Symbol.iterator; plain objects don't
if (typeof headers[Symbol.iterator] === "function") {
const obj = {};
for (const [name, value] of headers) {
obj[name] = value;
}
return obj;
}
return { ...headers };
}
/**
* Check if a request header exists (case-insensitive).
* Request headers may have user-controlled casing.
*/
#hasRequestHeader(requestHeaders, name) {
const lowerName = name.toLowerCase();
return Object.keys(requestHeaders).some(key => key.toLowerCase() === lowerName);
}
/**
* Delete a request header (case-insensitive).
* Request headers may have user-controlled casing. Mutates the object in place.
*/
#deleteRequestHeader(requestHeaders, name) {
const lowerName = name.toLowerCase();
for (const key of Object.keys(requestHeaders)) {
if (key.toLowerCase() === lowerName) {
delete requestHeaders[key];
}
}
}
/**
* Set default request headers if not already present.
* Mutates the headers object in place.
*/
#setDefaultHeaders(requestHeaders) {
if (!this.#hasRequestHeader(requestHeaders, "User-Agent")) {
requestHeaders["User-Agent"] = this.#userAgent;
}
if (!this.#hasRequestHeader(requestHeaders, "Accept-Language")) {
requestHeaders["Accept-Language"] = "en";
}
if (!this.#hasRequestHeader(requestHeaders, "Accept")) {
requestHeaders.Accept = "*/*";
}
if (!this.#hasRequestHeader(requestHeaders, "Accept-Encoding")) {
requestHeaders["Accept-Encoding"] = "gzip, deflate";
}
}
/**
* Extract and store cookies from response headers.
*/
#storeCookiesFromHeaders(headers, url) {
if (!headers["set-cookie"]) {
return;
}
const cookies = Array.isArray(headers["set-cookie"]) ?
headers["set-cookie"] :
[headers["set-cookie"]];
for (const cookie of cookies) {
this.#cookieJar.setCookieSync(cookie, url, { ignoreError: true });
}
}
// Dispatcher API methods - forward close/destroy to base dispatcher
close(...args) {
return this.#baseDispatcher.close(...args);
}
destroy(...args) {
return this.#baseDispatcher.destroy(...args);
}
/**
* Create a new JSDOMDispatcher with additional interceptors.
* The new interceptors are added as the outermost (first to see requests, last to see responses).
*/
compose(...additionalInterceptors) {
return new JSDOMDispatcher({
baseDispatcher: this.#baseDispatcher,
cookieJar: this.#cookieJar,
userAgent: this.#userAgent,
userInterceptors: [...additionalInterceptors, ...this.#userInterceptors]
});
}
get closed() {
return this.#baseDispatcher.closed;
}
get destroyed() {
return this.#baseDispatcher.destroyed;
}
}
/**
* High-level GET fetch that collects the full response body. Used for subresources and `JSDOM.fromURL()`.
*
* @param {Dispatcher} dispatcher - The undici dispatcher to use
* @param {object} opts - Request options
* @param {string} opts.url - The URL to fetch
* @param {object} [opts.headers] - Request headers (include Referer if needed)
* @param {AbortSignal} [opts.signal] - Abort signal
* @param {Element} [opts.element] - The element initiating the request (default: null)
* @returns {Promise<{status: number, headers: object, body: Uint8Array, url: string, ok: boolean}>}
*/
async function fetchCollected(dispatcher, { url, headers, signal, element = null }) {
const urlRecord = parseURL(url);
if (!urlRecord) {
throw new TypeError(`Invalid URL: ${url}`);
}
const response = await dispatcher.request({
origin: serializeURLOrigin(urlRecord),
path: serializePathForUndici(urlRecord),
method: "GET",
headers,
signal,
opaque: { element, url }
});
const body = await response.body.bytes();
// Get final URL from context (set by dispatcher after handling redirects)
const finalURL = serializeURL(response.context.finalURL);
return {
status: response.statusCode,
headers: response.headers,
body,
url: finalURL,
ok: response.statusCode >= 200 && response.statusCode < 300
};
}
/**
* Serialize a URL record's path and query for undici's `path` option.
*/
function serializePathForUndici(urlRecord) {
return serializePath(urlRecord) + (urlRecord.query ? "?" + urlRecord.query : "");
}
module.exports = {
JSDOMDispatcher,
DEFAULT_USER_AGENT,
fetchCollected
};

View File

@@ -0,0 +1,116 @@
"use strict";
const idlUtils = require("../../living/generated/utils");
const { fireAnEvent } = require("../../living/helpers/events");
const { fetchCollected } = require("./jsdom-dispatcher");
module.exports = class PerDocumentResourceLoader {
constructor(document) {
this._document = document;
this._defaultEncoding = document._encoding;
const defaultView = document._defaultView;
this._dispatcher = defaultView ? defaultView._dispatcher : null;
this._loadSubresources = defaultView ? defaultView._loadSubresources : false;
this._requestManager = document._requestManager;
this._queue = document._queue;
this._deferQueue = document._deferQueue;
this._asyncQueue = document._asyncQueue;
}
fetch(url, { element, onLoad, onError }) {
if (!this._loadSubresources) {
return null;
}
const abortController = new AbortController();
// Add it to the request manager. The request manager is very old code, but it works with the contract of "has an
// `abort()` method". One day this whole subsystem will be refactored to use `AbortController`s natively, but for
// now this just happens to work.
//
// Note that we add the controller now, before calling `fetchCollected()`, so that if any interceptors or other code
// calls `window.close()`, the abort controller is already registered and will see the abort.
this._requestManager.add(abortController);
const fetchPromise = fetchCollected(this._dispatcher, {
url,
headers: { Referer: this._document.URL },
signal: abortController.signal,
element: idlUtils.wrapperForImpl(element)
});
const onErrorWrapped = cause => {
this._requestManager.remove(abortController);
// If the request was aborted, don't fire error events
if (cause && cause.name === "AbortError") {
return Promise.resolve();
}
if (onError) {
onError(cause);
}
fireAnEvent("error", element);
const jsomError = new Error(`Could not load ${element.localName}: "${url}"`, { cause });
jsomError.type = "resource-loading";
jsomError.url = url;
this._document._defaultView._virtualConsole.emit("jsdomError", jsomError);
return Promise.resolve();
};
const onLoadWrapped = response => {
this._requestManager.remove(abortController);
// Extract data and create a response-like object for compatibility
const { body: data, status, headers, url: responseURL } = response;
const responseObj = {
ok: status >= 200 && status < 300,
status,
headers: {
get(name) {
return headers[name.toLowerCase()] ?? null;
}
},
url: responseURL
};
try {
const result = onLoad ? onLoad(data, responseObj) : undefined;
return Promise.resolve(result)
.then(() => {
fireAnEvent("load", element);
return Promise.resolve();
})
.catch(err => {
return onErrorWrapped(err);
});
} catch (err) {
return onErrorWrapped(err);
}
};
// Create a wrapper object that can be used by the queue system
const request = {
then: (onFulfilled, onRejected) => fetchPromise.then(onFulfilled, onRejected),
catch: onRejected => fetchPromise.catch(onRejected)
};
if (element.localName === "script" && element.hasAttributeNS(null, "async")) {
this._asyncQueue.push(request, onLoadWrapped, onErrorWrapped, this._queue.getLastScript());
} else if (
element.localName === "script" &&
element.hasAttributeNS(null, "defer") &&
this._document.readyState !== "interactive") {
this._deferQueue.push(request, onLoadWrapped, onErrorWrapped, false, element);
} else {
this._queue.push(request, onLoadWrapped, onErrorWrapped, false, element);
}
return request;
}
};

View File

@@ -0,0 +1,171 @@
"use strict";
const { Readable } = require("stream");
const { sendStreamResponse } = require("./stream-handler");
/**
* Creates a user-friendly `undici` interceptor for jsdom.
*
* This helper allows users to intercept requests using a callback that receives a `Request` object and can return a
* promise for a `Response` to provide a synthetic response, or a promise for `undefined` to pass through.
*
* @param {function} fn - Async callback function that receives (request, context) and can return a Response
* @returns {function} An undici interceptor
*
* @example
* const dom = new JSDOM(html, {
* interceptors: [
* requestInterceptor(async (request, { element }) => {
* console.log(`${element?.localName || 'XHR'} requested ${request.url}`);
* if (request.url.endsWith('/test.js')) {
* return new Response('window.mocked = true;', {
* headers: { 'Content-Type': 'application/javascript' }
* });
* }
* // Return undefined to let the request pass through
* })
* ]
* });
*
* ## Why this doesn't use undici's DecoratorHandler pattern
*
* The standard undici interceptor pattern (see e.g. undici/lib/interceptor/dump.js) uses DecoratorHandler
* to wrap handler callbacks. That pattern calls `dispatch()` synchronously, then observes/modifies the
* request and response as they flow through the handler callbacks.
*
* This interceptor needs to support async user functions that can BLOCK the request and potentially
* REPLACE it with a synthetic response. This requires:
*
* 1. Waiting for the async user function BEFORE deciding whether to dispatch
* 2. For synthetic responses, NEVER calling dispatch() at all
*
* Since synthetic responses bypass the normal undici dispatch flow entirely, there's no underlying
* dispatcher (Agent/Pool) to create a real controller for us. We provide our own controller object
* that delegates to a Node.js Readable stream for pause/resume/abort support, following the pattern
* from undici/lib/interceptor/cache.js.
*/
module.exports = function requestInterceptor(fn) {
return dispatch => (options, handler) => {
const { element = null, url } = options.opaque || {};
const abortController = new AbortController();
// Create undici controller and wrapped handler using the signal handler helper.
// The undici controller reflects abortController.signal's state and forwards to inner undici controller.
const { undiciController, wrappedHandler } = createSignalHandler(handler, abortController);
// Call onRequestStart immediately to wire into the abort chain.
handler.onRequestStart?.(undiciController, {});
// Build Request object with our signal
const requestInit = {
method: options.method || "GET",
headers: options.headers,
signal: abortController.signal
};
if (options.body !== undefined && options.body !== null) {
requestInit.body = options.body;
requestInit.duplex = "half";
}
if (options.referrer) {
requestInit.referrer = options.referrer;
}
const request = new Request(url, requestInit);
new Promise(resolve => {
resolve(fn(request, { element }));
})
.then(response => {
if (response instanceof Response) {
// Send synthetic response without ever starting real request
// response.body can be null for responses with no body
const stream = response.body ? Readable.fromWeb(response.body) : Readable.from([]);
sendStreamResponse(wrappedHandler, stream, {
status: response.status,
statusText: response.statusText,
headers: headersToUndici(response.headers)
});
} else if (response !== undefined) {
throw new TypeError("requestInterceptor callback must return undefined or a Response");
} else if (!abortController.signal.aborted) {
// Pass through to real request
dispatch(options, wrappedHandler);
}
})
.catch(error => {
handler.onResponseError?.(undiciController, error);
});
// Return true to indicate request is being handled
return true;
};
};
/**
* Creates an undici controller and wrapped handler that bridge an AbortController to undici's dispatch protocol.
*
* The undici controller reflects the AbortController's signal state and captures an inner undici controller
* (from pass-through dispatch or synthetic stream) for forwarding pause/resume/abort.
*/
function createSignalHandler(handler, abortController) {
let innerUndiciController = null;
const undiciController = {
abort(reason) {
abortController.abort(reason);
innerUndiciController?.abort(reason);
},
pause() {
innerUndiciController?.pause();
},
resume() {
innerUndiciController?.resume();
},
get paused() {
return innerUndiciController?.paused ?? false;
},
get aborted() {
return abortController.signal.aborted;
},
get reason() {
return abortController.signal.reason;
}
};
const wrappedHandler = {
onRequestStart(controller) {
innerUndiciController = controller;
},
onRequestUpgrade(...args) {
handler.onRequestUpgrade?.(...args);
},
onResponseStart(...args) {
handler.onResponseStart?.(...args);
},
onResponseData(...args) {
handler.onResponseData?.(...args);
},
onResponseEnd(...args) {
handler.onResponseEnd?.(...args);
},
onResponseError(...args) {
handler.onResponseError?.(...args);
}
};
return { undiciController, wrappedHandler };
}
/**
* Converts a Headers object to the format undici expects.
* Handles multiple Set-Cookie headers via getSetCookie().
*/
function headersToUndici(headers) {
const result = {};
for (const [key, value] of headers) {
result[key] = value;
}
const cookies = headers.getSetCookie();
if (cookies.length > 0) {
result["set-cookie"] = cookies;
}
return result;
}

View File

@@ -0,0 +1,33 @@
"use strict";
/**
* Manage all the request and it is able to abort
* all pending request.
*/
module.exports = class RequestManager {
constructor() {
this.openedRequests = [];
}
add(req) {
this.openedRequests.push(req);
}
remove(req) {
const idx = this.openedRequests.indexOf(req);
if (idx !== -1) {
this.openedRequests.splice(idx, 1);
}
}
close() {
for (const openedRequest of this.openedRequests) {
openedRequest.abort();
}
this.openedRequests = [];
}
size() {
return this.openedRequests.length;
}
};

View File

@@ -0,0 +1,142 @@
"use strict";
/**
* Queue for all the resources to be download except async scripts.
* Async scripts have their own queue AsyncResourceQueue.
*/
module.exports = class ResourceQueue {
constructor({ paused, asyncQueue } = {}) {
this.paused = Boolean(paused);
this._asyncQueue = asyncQueue;
}
getLastScript() {
let head = this.tail;
while (head) {
if (head.isScript) {
return head;
}
head = head.prev;
}
return null;
}
_moreScripts() {
let found = false;
let head = this.tail;
while (head && !found) {
found = head.isScript;
head = head.prev;
}
return found;
}
_notify() {
if (this._listener) {
this._listener();
}
}
setListener(listener) {
this._listener = listener;
}
push(request, onLoad, onError, keepLast, element) {
const isScript = element ? element.localName === "script" : false;
if (!request) {
if (isScript && !this._moreScripts()) {
return onLoad();
}
request = Promise.resolve();
}
const q = this;
const item = {
isScript,
err: null,
element,
fired: false,
data: null,
keepLast,
prev: q.tail,
check() {
if (!q.paused && !this.prev && this.fired) {
let promise;
if (this.err && onError) {
promise = onError(this.err);
}
if (!this.err && onLoad) {
promise = onLoad(this.data);
}
Promise.resolve(promise)
.then(() => {
if (this.next) {
this.next.prev = null;
this.next.check();
} else { // q.tail===this
q.tail = null;
q._notify();
}
this.finished = true;
if (q._asyncQueue) {
q._asyncQueue.notifyItem(this);
}
});
}
}
};
if (q.tail) {
if (q.tail.keepLast) {
// if the tail is the load event in document and we receive a new element to load
// we should add this new request before the load event.
if (q.tail.prev) {
q.tail.prev.next = item;
}
item.prev = q.tail.prev;
q.tail.prev = item;
item.next = q.tail;
} else {
q.tail.next = item;
q.tail = item;
}
} else {
q.tail = item;
}
return request
.then(data => {
item.fired = 1;
item.data = data;
item.check();
})
.catch(err => {
item.fired = true;
item.err = err;
item.check();
});
}
resume() {
if (!this.paused) {
return;
}
this.paused = false;
let head = this.tail;
while (head && head.prev) {
head = head.prev;
}
if (head) {
head.check();
}
}
};

View File

@@ -0,0 +1,89 @@
"use strict";
/**
* Sends a response to an undici handler by streaming data from a Node.js Readable stream.
*
* ## Why this exists
*
* undici's new handler API (onRequestStart, onResponseStart, onResponseData, onResponseEnd, onResponseError)
* requires a "controller" object with pause/resume/abort methods. When responses flow through undici's
* normal network stack, undici provides this controller. But when we generate responses ourselves
* (e.g., for file: URLs, data: URLs, or synthetic responses from interceptors), we need to provide
* our own controller.
*
* This helper creates a controller backed by a Node.js Readable stream, giving callers proper
* pause/resume and abort support. It follows the pattern from undici/lib/interceptor/cache.js.
*
* ## Usage
*
* ```javascript
* const stream = fs.createReadStream(filePath);
* // or: const stream = Readable.from(buffer);
* // or: const stream = Readable.fromWeb(response.body);
*
* sendStreamResponse(handler, stream, {
* status: 200,
* statusText: "OK",
* headers: { "content-type": "text/plain" },
* context: { history: ["file:///path/to/file"] }
* });
* ```
*
* The function handles all stream events and translates them to handler callbacks.
* If the stream is destroyed (e.g., via controller.abort()), pending operations are cancelled.
*
* @param {object} handler - undici handler with new API methods (onRequestStart, onResponseStart, etc.)
* @param {Readable} stream - Node.js Readable stream containing the response body
* @param {object} options - Response metadata
* @param {number} options.status - HTTP status code
* @param {string} [options.statusText] - HTTP status text (default: "")
* @param {object} [options.headers] - Response headers as {name: value} object (default: {})
* @param {object} [options.context] - Context object passed to onRequestStart (default: {})
*/
function sendStreamResponse(handler, stream, { status, statusText = "", headers = {}, context = {} }) {
const controller = {
resume() {
stream.resume();
},
pause() {
stream.pause();
},
get paused() {
return stream.isPaused();
},
get aborted() {
return stream.errored !== null;
},
get reason() {
return stream.errored;
},
abort(reason) {
stream.destroy(reason);
}
};
stream
.on("error", err => {
if (!stream.readableEnded) {
handler.onResponseError?.(controller, err);
}
})
.on("close", () => {
if (!stream.errored) {
handler.onResponseEnd?.(controller, {});
}
})
.on("data", chunk => {
handler.onResponseData?.(controller, chunk);
});
handler.onRequestStart?.(controller, context);
if (stream.destroyed) {
return;
}
handler.onResponseStart?.(controller, status, headers, statusText);
}
module.exports = { sendStreamResponse };

65
node_modules/jsdom/lib/jsdom/level2/style.js generated vendored Normal file
View File

@@ -0,0 +1,65 @@
"use strict";
const cssstyle = require("cssstyle");
exports.addToCore = core => {
// What works now:
// - Accessing the rules defined in individual stylesheets
// - Modifications to style content attribute are reflected in style property
// - Modifications to style property are reflected in style content attribute
// TODO
// - Modifications to style element's textContent are reflected in sheet property.
// - Modifications to style element's sheet property are reflected in textContent.
// - Modifications to link.href property are reflected in sheet property.
// - Less-used features of link: disabled
// - Less-used features of style: disabled, scoped, title
// - CSSOM-View
// - getComputedStyle(): requires default stylesheet, cascading, inheritance,
// filtering by @media (screen? print?), layout for widths/heights
// - Load events are not in the specs, but apparently some browsers
// implement something. Should onload only fire after all @imports have been
// loaded, or only the primary sheet?
const cssom = require("@acemir/cssom").setup({ globalObject: core._globalObject });
core.StyleSheet = cssom.StyleSheet;
core.MediaList = cssom.MediaList;
core.CSSStyleSheet = cssom.CSSStyleSheet;
core.CSSRule = cssom.CSSRule;
core.CSSGroupingRule = cssom.CSSGroupingRule;
core.CSSNestedDeclarations = cssom.CSSNestedDeclarations;
core.CSSStyleRule = cssom.CSSStyleRule;
core.CSSMediaRule = cssom.CSSMediaRule;
core.CSSImportRule = cssom.CSSImportRule;
core.CSSConditionRule = cssom.CSSConditionRule;
core.CSSContainerRule = cssom.CSSContainerRule;
core.CSSScopeRule = cssom.CSSScopeRule;
core.CSSSupportsRule = cssom.CSSSupportsRule;
core.CSSLayerBlockRule = cssom.CSSLayerBlockRule;
core.CSSLayerStatementRule = cssom.CSSLayerStatementRule;
core.CSSStyleDeclaration = cssstyle.CSSStyleDeclaration;
// Relevant specs
// http://www.w3.org/TR/DOM-Level-2-Style (2000)
// http://www.w3.org/TR/cssom-view/ (2008)
// http://dev.w3.org/csswg/cssom/ (2010) Meant to replace DOM Level 2 Style
// http://www.whatwg.org/specs/web-apps/current-work/multipage/ HTML5, of course
// http://dev.w3.org/csswg/css-style-attr/ not sure what's new here
// Objects that aren't in cssom library but should be:
// CSSRuleList (cssom just uses array)
// CSSFontFaceRule
// CSSPageRule
// These rules don't really make sense to implement, so CSSOM draft makes them
// obsolete.
// CSSCharsetRule
// CSSUnknownRule
// These objects are considered obsolete by CSSOM draft, although modern
// browsers implement them.
// CSSValue
// CSSPrimitiveValue
// CSSValueList
// RGBColor
// Rect
// Counter
};

1875
node_modules/jsdom/lib/jsdom/level3/xpath.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
"use strict";
const AbortSignal = require("../generated/AbortSignal");
class AbortControllerImpl {
constructor(globalObject) {
this.signal = AbortSignal.createImpl(globalObject, []);
}
abort(reason) {
this.signal._signalAbort(reason);
}
}
module.exports = {
implementation: AbortControllerImpl
};

View File

@@ -0,0 +1,131 @@
"use strict";
const { setupForSimpleEventAccessors } = require("../helpers/create-event-accessor");
const { fireAnEvent } = require("../helpers/events");
const EventTargetImpl = require("../events/EventTarget-impl").implementation;
const AbortSignal = require("../generated/AbortSignal");
const DOMException = require("../generated/DOMException");
class AbortSignalImpl extends EventTargetImpl {
constructor(globalObject, args, privateData) {
super(globalObject, args, privateData);
// make event firing possible
this._ownerDocument = globalObject.document;
this.reason = undefined;
this.abortAlgorithms = new Set();
this._dependent = false;
this._sourceSignals = new Set();
this._dependentSignals = new Set();
}
get aborted() {
return this.reason !== undefined;
}
throwIfAborted() {
if (this.aborted) {
throw this.reason;
}
}
static abort(globalObject, reason) {
const abortSignal = AbortSignal.createImpl(globalObject, []);
if (reason !== undefined) {
abortSignal.reason = reason;
} else {
abortSignal.reason = DOMException.create(globalObject, ["The operation was aborted.", "AbortError"]);
}
return abortSignal;
}
// https://dom.spec.whatwg.org/#abortsignal-dependent
static any(globalObject, signals) {
const resultSignal = AbortSignal.createImpl(globalObject, []);
for (const signal of signals) {
if (signal.aborted) {
resultSignal.reason = signal.reason;
return resultSignal;
}
}
resultSignal.dependent = true;
for (const signal of signals) {
if (!signal.dependent) {
resultSignal._sourceSignals.add(signal);
signal._dependentSignals.add(resultSignal);
} else {
for (const sourceSignal of signal._sourceSignals) {
if (!sourceSignal.aborted && !sourceSignal.dependent) {
resultSignal._sourceSignals.add(sourceSignal);
sourceSignal._dependentSignals.add(resultSignal);
}
}
}
}
return resultSignal;
}
static timeout(globalObject, milliseconds) {
const signal = AbortSignal.createImpl(globalObject, []);
globalObject.setTimeout(() => {
signal._signalAbort(DOMException.create(globalObject, ["The operation timed out.", "TimeoutError"]));
}, milliseconds);
return signal;
}
// https://dom.spec.whatwg.org/#abortsignal-signal-abort
_signalAbort(reason) {
if (this.aborted) {
return;
}
if (reason !== undefined) {
this.reason = reason;
} else {
this.reason = DOMException.create(this._globalObject, ["The operation was aborted.", "AbortError"]);
}
const dependentSignalsToAbort = [];
for (const dependentSignal of this._dependentSignals) {
if (!dependentSignal.aborted) {
dependentSignal.reason = this.reason;
dependentSignalsToAbort.push(dependentSignal);
}
}
this._runAbortStep();
for (const dependentSignal of dependentSignalsToAbort) {
dependentSignal._runAbortStep();
}
}
_runAbortStep() {
for (const algorithm of this.abortAlgorithms) {
algorithm();
}
this.abortAlgorithms.clear();
fireAnEvent("abort", this);
}
_addAlgorithm(algorithm) {
if (this.aborted) {
return;
}
this.abortAlgorithms.add(algorithm);
}
_removeAlgorithm(algorithm) {
this.abortAlgorithms.delete(algorithm);
}
}
setupForSimpleEventAccessors(AbortSignalImpl.prototype, ["abort"]);
module.exports = {
implementation: AbortSignalImpl
};

312
node_modules/jsdom/lib/jsdom/living/attributes.js generated vendored Normal file
View File

@@ -0,0 +1,312 @@
"use strict";
const DOMException = require("./generated/DOMException");
const { HTML_NS } = require("./helpers/namespaces");
const { asciiLowercase } = require("./helpers/strings");
const { queueAttributeMutationRecord } = require("./helpers/mutation-observers");
const { enqueueCECallbackReaction } = require("./helpers/custom-elements");
// The following three are for https://dom.spec.whatwg.org/#concept-element-attribute-has. We don't just have a
// predicate tester since removing that kind of flexibility gives us the potential for better future optimizations.
/* eslint-disable no-restricted-properties */
exports.hasAttribute = function (element, A) {
return element._attributeList.includes(A);
};
exports.hasAttributeByName = function (element, name) {
return element._attributesByNameMap.has(name);
};
exports.hasAttributeByNameNS = function (element, namespace, localName) {
return element._attributeList.some(attribute => {
return attribute._localName === localName && attribute._namespace === namespace;
});
};
// https://dom.spec.whatwg.org/#concept-element-attributes-change
exports.changeAttribute = (element, attribute, value) => {
const { _localName, _namespace, _value } = attribute;
queueAttributeMutationRecord(element, _localName, _namespace, _value);
if (element._ceState === "custom") {
enqueueCECallbackReaction(element, "attributeChangedCallback", [
_localName,
_value,
value,
_namespace
]);
}
attribute._value = value;
// Run jsdom hooks; roughly correspond to spec's "An attribute is set and an attribute is changed."
element._attrModified(attribute._qualifiedName, value, _value);
};
// https://dom.spec.whatwg.org/#concept-element-attributes-append
exports.appendAttribute = function (element, attribute) {
const { _localName, _namespace, _value } = attribute;
queueAttributeMutationRecord(element, _localName, _namespace, null);
if (element._ceState === "custom") {
enqueueCECallbackReaction(element, "attributeChangedCallback", [
_localName,
null,
_value,
_namespace
]);
}
const attributeList = element._attributeList;
attributeList.push(attribute);
attribute._element = element;
// Sync name cache
const name = attribute._qualifiedName;
const cache = element._attributesByNameMap;
let entry = cache.get(name);
if (!entry) {
entry = [];
cache.set(name, entry);
}
entry.push(attribute);
// Run jsdom hooks; roughly correspond to spec's "An attribute is set and an attribute is added."
element._attrModified(name, _value, null);
};
exports.removeAttribute = function (element, attribute) {
// https://dom.spec.whatwg.org/#concept-element-attributes-remove
const { _localName, _namespace, _value } = attribute;
queueAttributeMutationRecord(element, _localName, _namespace, _value);
if (element._ceState === "custom") {
enqueueCECallbackReaction(element, "attributeChangedCallback", [
_localName,
_value,
null,
_namespace
]);
}
const attributeList = element._attributeList;
for (let i = 0; i < attributeList.length; ++i) {
if (attributeList[i] === attribute) {
attributeList.splice(i, 1);
attribute._element = null;
// Sync name cache
const name = attribute._qualifiedName;
const cache = element._attributesByNameMap;
const entry = cache.get(name);
entry.splice(entry.indexOf(attribute), 1);
if (entry.length === 0) {
cache.delete(name);
}
// Run jsdom hooks; roughly correspond to spec's "An attribute is removed."
element._attrModified(name, null, attribute._value);
return;
}
}
};
exports.replaceAttribute = function (element, oldAttr, newAttr) {
// https://dom.spec.whatwg.org/#concept-element-attributes-replace
const { _localName, _namespace, _value } = oldAttr;
queueAttributeMutationRecord(element, _localName, _namespace, _value);
if (element._ceState === "custom") {
enqueueCECallbackReaction(element, "attributeChangedCallback", [
_localName,
_value,
newAttr._value,
_namespace
]);
}
const attributeList = element._attributeList;
for (let i = 0; i < attributeList.length; ++i) {
if (attributeList[i] === oldAttr) {
attributeList.splice(i, 1, newAttr);
oldAttr._element = null;
newAttr._element = element;
// Sync name cache
const name = newAttr._qualifiedName;
const cache = element._attributesByNameMap;
let entry = cache.get(name);
if (!entry) {
entry = [];
cache.set(name, entry);
}
entry.splice(entry.indexOf(oldAttr), 1, newAttr);
// Run jsdom hooks; roughly correspond to spec's "An attribute is set and an attribute is changed."
element._attrModified(name, newAttr._value, oldAttr._value);
return;
}
}
};
exports.getAttributeByName = function (element, name) {
// https://dom.spec.whatwg.org/#concept-element-attributes-get-by-name
if (element._namespaceURI === HTML_NS &&
element._ownerDocument._parsingMode === "html") {
name = asciiLowercase(name);
}
const cache = element._attributesByNameMap;
const entry = cache.get(name);
if (!entry) {
return null;
}
return entry[0];
};
exports.getAttributeByNameNS = function (element, namespace, localName) {
// https://dom.spec.whatwg.org/#concept-element-attributes-get-by-namespace
if (namespace === "") {
namespace = null;
}
const attributeList = element._attributeList;
for (let i = 0; i < attributeList.length; ++i) {
const attr = attributeList[i];
if (attr._namespace === namespace && attr._localName === localName) {
return attr;
}
}
return null;
};
// Both of the following functions implement https://dom.spec.whatwg.org/#concept-element-attributes-get-value.
// Separated them into two to keep symmetry with other functions.
exports.getAttributeValue = function (element, localName) {
const attr = exports.getAttributeByNameNS(element, null, localName);
if (!attr) {
return "";
}
return attr._value;
};
exports.getAttributeValueNS = function (element, namespace, localName) {
const attr = exports.getAttributeByNameNS(element, namespace, localName);
if (!attr) {
return "";
}
return attr._value;
};
exports.setAttribute = function (element, attr) {
// https://dom.spec.whatwg.org/#concept-element-attributes-set
if (attr._element !== null && attr._element !== element) {
throw DOMException.create(element._globalObject, ["The attribute is in use.", "InUseAttributeError"]);
}
const oldAttr = exports.getAttributeByNameNS(element, attr._namespace, attr._localName);
if (oldAttr === attr) {
return attr;
}
if (oldAttr !== null) {
exports.replaceAttribute(element, oldAttr, attr);
} else {
exports.appendAttribute(element, attr);
}
return oldAttr;
};
exports.setAttributeValue = function (element, localName, value, prefix, namespace) {
// https://dom.spec.whatwg.org/#concept-element-attributes-set-value
if (prefix === undefined) {
prefix = null;
}
if (namespace === undefined) {
namespace = null;
}
const attribute = exports.getAttributeByNameNS(element, namespace, localName);
if (attribute === null) {
const newAttribute = element._ownerDocument._createAttribute({
namespace,
namespacePrefix: prefix,
localName,
value
});
exports.appendAttribute(element, newAttribute);
return;
}
exports.changeAttribute(element, attribute, value);
};
// https://dom.spec.whatwg.org/#set-an-existing-attribute-value
exports.setAnExistingAttributeValue = (attribute, value) => {
const element = attribute._element;
if (element === null) {
attribute._value = value;
} else {
exports.changeAttribute(element, attribute, value);
}
};
exports.removeAttributeByName = function (element, name) {
// https://dom.spec.whatwg.org/#concept-element-attributes-remove-by-name
const attr = exports.getAttributeByName(element, name);
if (attr !== null) {
exports.removeAttribute(element, attr);
}
return attr;
};
exports.removeAttributeByNameNS = function (element, namespace, localName) {
// https://dom.spec.whatwg.org/#concept-element-attributes-remove-by-namespace
const attr = exports.getAttributeByNameNS(element, namespace, localName);
if (attr !== null) {
exports.removeAttribute(element, attr);
}
return attr;
};
exports.attributeNames = function (element) {
// Needed by https://dom.spec.whatwg.org/#dom-element-getattributenames
return element._attributeList.map(a => a._qualifiedName);
};
exports.hasAttributes = function (element) {
// Needed by https://dom.spec.whatwg.org/#dom-element-hasattributes
return element._attributeList.length > 0;
};

View File

@@ -0,0 +1,60 @@
"use strict";
const { setAnExistingAttributeValue } = require("../attributes.js");
const NodeImpl = require("../nodes/Node-impl.js").implementation;
const { ATTRIBUTE_NODE } = require("../node-type.js");
exports.implementation = class AttrImpl extends NodeImpl {
constructor(globalObject, args, privateData) {
super(globalObject, args, privateData);
this._namespace = privateData.namespace !== undefined ? privateData.namespace : null;
this._namespacePrefix = privateData.namespacePrefix !== undefined ? privateData.namespacePrefix : null;
this._localName = privateData.localName;
this._value = privateData.value !== undefined ? privateData.value : "";
this._element = privateData.element !== undefined ? privateData.element : null;
this.nodeType = ATTRIBUTE_NODE;
this.specified = true;
}
get namespaceURI() {
return this._namespace;
}
get prefix() {
return this._namespacePrefix;
}
get localName() {
return this._localName;
}
get name() {
return this._qualifiedName;
}
get nodeName() {
return this._qualifiedName;
}
get value() {
return this._value;
}
set value(value) {
setAnExistingAttributeValue(this, value);
}
get ownerElement() {
return this._element;
}
get _qualifiedName() {
// https://dom.spec.whatwg.org/#concept-attribute-qualified-name
if (this._namespacePrefix === null) {
return this._localName;
}
return this._namespacePrefix + ":" + this._localName;
}
};

View File

@@ -0,0 +1,78 @@
"use strict";
const DOMException = require("../generated/DOMException");
const idlUtils = require("../generated/utils.js");
const attributes = require("../attributes.js");
const { HTML_NS } = require("../helpers/namespaces");
exports.implementation = class NamedNodeMapImpl {
constructor(globalObject, args, privateData) {
this._element = privateData.element;
this._globalObject = globalObject;
}
get _attributeList() {
return this._element._attributeList;
}
get [idlUtils.supportedPropertyIndices]() {
return this._attributeList.keys();
}
get length() {
return this._attributeList.length;
}
item(index) {
if (index >= this._attributeList.length) {
return null;
}
return this._attributeList[index];
}
get [idlUtils.supportedPropertyNames]() {
const names = new Set(this._attributeList.map(a => a._qualifiedName));
const el = this._element;
if (el._namespaceURI === HTML_NS && el._ownerDocument._parsingMode === "html") {
for (const name of names) {
const lowercaseName = name.toLowerCase();
if (lowercaseName !== name) {
names.delete(name);
}
}
}
return names;
}
getNamedItem(qualifiedName) {
return attributes.getAttributeByName(this._element, qualifiedName);
}
getNamedItemNS(namespace, localName) {
return attributes.getAttributeByNameNS(this._element, namespace, localName);
}
setNamedItem(attr) {
// eslint-disable-next-line no-restricted-properties
return attributes.setAttribute(this._element, attr);
}
setNamedItemNS(attr) {
// eslint-disable-next-line no-restricted-properties
return attributes.setAttribute(this._element, attr);
}
removeNamedItem(qualifiedName) {
const attr = attributes.removeAttributeByName(this._element, qualifiedName);
if (attr === null) {
throw DOMException.create(this._globalObject, [
"Tried to remove an attribute that was not present",
"NotFoundError"
]);
}
return attr;
}
removeNamedItemNS(namespace, localName) {
const attr = attributes.removeAttributeByNameNS(this._element, namespace, localName);
if (attr === null) {
throw DOMException.create(this._globalObject, [
"Tried to remove an attribute that was not present",
"NotFoundError"
]);
}
return attr;
}
};

View File

@@ -0,0 +1,75 @@
"use strict";
const ValidityState = require("../generated/ValidityState");
const { isDisabled } = require("../helpers/form-controls");
const { closest } = require("../helpers/traversal");
const { fireAnEvent } = require("../helpers/events");
exports.implementation = class DefaultConstraintValidationImpl {
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-cva-willvalidate
get willValidate() {
return this._isCandidateForConstraintValidation();
}
get validity() {
if (!this._validity) {
this._validity = ValidityState.createImpl(this._globalObject, [], {
element: this
});
}
return this._validity;
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-cva-checkvalidity
checkValidity() {
if (!this._isCandidateForConstraintValidation()) {
return true;
}
if (this._satisfiesConstraints()) {
return true;
}
fireAnEvent("invalid", this, undefined, { cancelable: true });
return false;
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-cva-setcustomvalidity
setCustomValidity(message) {
this._customValidityErrorMessage = message;
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-cva-reportvalidity
// Since jsdom has no user interaction, it's the same as #checkValidity
reportValidity() {
return this.checkValidity();
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#dom-cva-validationmessage
get validationMessage() {
const { validity } = this;
if (!this._isCandidateForConstraintValidation() || this._satisfiesConstraints()) {
return "";
}
const isSufferingFromCustomError = validity.customError;
if (isSufferingFromCustomError) {
return this._customValidityErrorMessage;
}
return "Constraints not satisfied";
}
_isCandidateForConstraintValidation() {
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fe-disabled
return !isDisabled(this) &&
// If an element has a datalist element ancestor,
// it is barred from constraint validation.
closest(this, "datalist") === null &&
!this._barredFromConstraintValidationSpecialization();
}
_isBarredFromConstraintValidation() {
return !this._isCandidateForConstraintValidation();
}
_satisfiesConstraints() {
return this.validity.valid;
}
};

View File

@@ -0,0 +1,66 @@
"use strict";
exports.implementation = class ValidityStateImpl {
constructor(globalObject, args, privateData) {
const { element, state = {} } = privateData;
this._element = element;
this._state = state;
}
get badInput() {
return this._failsConstraint("badInput");
}
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#suffering-from-a-custom-error
get customError() {
return this._element._customValidityErrorMessage !== "";
}
get patternMismatch() {
return this._failsConstraint("patternMismatch");
}
get rangeOverflow() {
return this._failsConstraint("rangeOverflow");
}
get rangeUnderflow() {
return this._failsConstraint("rangeUnderflow");
}
get stepMismatch() {
return this._failsConstraint("stepMismatch");
}
get tooLong() {
return this._failsConstraint("tooLong");
}
get tooShort() {
return this._failsConstraint("tooShort");
}
get typeMismatch() {
return this._failsConstraint("typeMismatch");
}
get valueMissing() {
return this._failsConstraint("valueMissing");
}
_failsConstraint(method) {
const validationMethod = this._state[method];
if (validationMethod) {
return validationMethod();
}
return false;
}
get valid() {
return !(this.badInput || this.valueMissing || this.customError ||
this.patternMismatch || this.rangeOverflow || this.rangeUnderflow ||
this.stepMismatch || this.tooLong || this.tooShort || this.typeMismatch);
}
};

View File

@@ -0,0 +1,68 @@
"use strict";
const nodeCrypto = require("crypto");
const DOMException = require("../generated/DOMException");
// https://w3c.github.io/webcrypto/#crypto-interface
class CryptoImpl {
constructor(globalObject) {
this._globalObject = globalObject;
}
// https://w3c.github.io/webcrypto/#Crypto-method-getRandomValues
getRandomValues(array) {
const typeName = getTypedArrayTypeName(array);
if (!(typeName === "Int8Array" ||
typeName === "Uint8Array" ||
typeName === "Uint8ClampedArray" ||
typeName === "Int16Array" ||
typeName === "Uint16Array" ||
typeName === "Int32Array" ||
typeName === "Uint32Array" ||
typeName === "BigInt64Array" ||
typeName === "BigUint64Array")) {
throw DOMException.create(this._globalObject, [
`getRandomValues() only accepts integer typed arrays`,
"TypeMismatchError"
]);
}
if (array.byteLength > 65536) {
throw DOMException.create(this._globalObject, [
`getRandomValues() cannot generate more than 65536 bytes of random values; ` +
`${array.byteLength} bytes were requested`,
"QuotaExceededError"
]);
}
nodeCrypto.randomFillSync(array);
return array;
}
// https://w3c.github.io/webcrypto/#Crypto-method-randomUUID
randomUUID() {
return nodeCrypto.randomUUID();
}
}
exports.implementation = CryptoImpl;
// See #3395. Subclasses of TypedArrays should properly work, but we can't rely
// on instanceof because Uint8Array may be different across different windows -
// which can happen in JSDOM when running { runScripts: "dangerously" }. As a
// solution, we imitate the behavior of instanceof by walking the proottype
// chain.
function getTypedArrayTypeName(array) {
const target = array.constructor;
const chain = [target.name];
let proto = Object.getPrototypeOf(target);
while (proto) {
chain.push(proto.name);
proto = Object.getPrototypeOf(proto);
}
while (chain.length > 0 && chain[chain.length - 1] !== "TypedArray") {
chain.pop();
}
chain.reverse();
return chain[1];
}

View File

@@ -0,0 +1,38 @@
"use strict";
const idlUtils = require("../generated/utils.js");
exports.implementation = class StyleSheetList {
constructor() {
this._list = [];
}
get length() {
return this._list.length;
}
item(index) {
const result = this._list[index];
return result !== undefined ? result : null;
}
get [idlUtils.supportedPropertyIndices]() {
return this._list.keys();
}
_add(sheet) {
const { _list } = this;
if (!_list.includes(sheet)) {
_list.push(sheet);
}
}
_remove(sheet) {
const { _list } = this;
const index = _list.indexOf(sheet);
if (index >= 0) {
_list.splice(index, 1);
}
}
};

View File

@@ -0,0 +1,279 @@
"use strict";
const webIDLConversions = require("webidl-conversions");
const DOMException = require("../generated/DOMException");
const NODE_TYPE = require("../node-type");
const { HTML_NS } = require("../helpers/namespaces");
const { getHTMLElementInterface } = require("../helpers/create-element");
const { shadowIncludingInclusiveDescendantsIterator } = require("../helpers/shadow-dom");
const { isValidCustomElementName, tryUpgradeElement, enqueueCEUpgradeReaction } = require("../helpers/custom-elements");
const idlUtils = require("../generated/utils");
const IDLFunction = require("../generated/Function.js");
const HTMLUnknownElement = require("../generated/HTMLUnknownElement");
const LIFECYCLE_CALLBACKS = [
"connectedCallback",
"disconnectedCallback",
"adoptedCallback",
"attributeChangedCallback"
];
function convertToSequenceDOMString(obj) {
if (!obj || !obj[Symbol.iterator]) {
throw new TypeError("Invalid Sequence");
}
return Array.from(obj, webIDLConversions.DOMString);
}
// Returns true is the passed value is a valid constructor.
// Borrowed from: https://stackoverflow.com/a/39336206/3832710
function isConstructor(value) {
if (typeof value !== "function") {
return false;
}
try {
const P = new Proxy(value, {
construct() {
return {};
}
});
// eslint-disable-next-line no-new
new P();
return true;
} catch {
return false;
}
}
// https://html.spec.whatwg.org/#customelementregistry
class CustomElementRegistryImpl {
constructor(globalObject) {
this._customElementDefinitions = [];
this._elementDefinitionIsRunning = false;
this._whenDefinedPromiseMap = Object.create(null);
this._globalObject = globalObject;
}
// https://html.spec.whatwg.org/#dom-customelementregistry-define
define(name, constructor, options) {
const { _globalObject } = this;
const ctor = constructor.objectReference;
if (!isConstructor(ctor)) {
throw new TypeError("Constructor argument is not a constructor.");
}
if (!isValidCustomElementName(name)) {
throw DOMException.create(_globalObject, ["Name argument is not a valid custom element name.", "SyntaxError"]);
}
const nameAlreadyRegistered = this._customElementDefinitions.some(entry => entry.name === name);
if (nameAlreadyRegistered) {
throw DOMException.create(_globalObject, [
"This name has already been registered in the registry.",
"NotSupportedError"
]);
}
const ctorAlreadyRegistered = this._customElementDefinitions.some(entry => entry.objectReference === ctor);
if (ctorAlreadyRegistered) {
throw DOMException.create(_globalObject, [
"This constructor has already been registered in the registry.",
"NotSupportedError"
]);
}
let localName = name;
let extendsOption = null;
if (options !== undefined && options.extends) {
extendsOption = options.extends;
}
if (extendsOption !== null) {
if (isValidCustomElementName(extendsOption)) {
throw DOMException.create(_globalObject, [
"Option extends value can't be a valid custom element name.",
"NotSupportedError"
]);
}
const extendsInterface = getHTMLElementInterface(extendsOption);
if (extendsInterface === HTMLUnknownElement) {
throw DOMException.create(_globalObject, [
`${extendsOption} is an HTMLUnknownElement.`,
"NotSupportedError"
]);
}
localName = extendsOption;
}
if (this._elementDefinitionIsRunning) {
throw DOMException.create(_globalObject, [
"Invalid nested custom element definition.",
"NotSupportedError"
]);
}
this._elementDefinitionIsRunning = true;
let disableInternals = false;
let disableShadow = false;
let observedAttributes = [];
let formAssociated = false;
const lifecycleCallbacks = {
connectedCallback: null,
disconnectedCallback: null,
adoptedCallback: null,
attributeChangedCallback: null
};
let caughtError;
try {
const { prototype } = ctor;
if (typeof prototype !== "object") {
throw new TypeError("Invalid constructor prototype.");
}
for (const callbackName of LIFECYCLE_CALLBACKS) {
const callbackValue = prototype[callbackName];
if (callbackValue !== undefined) {
lifecycleCallbacks[callbackName] = IDLFunction.convert(_globalObject, callbackValue, {
context: `The lifecycle callback "${callbackName}"`
});
}
}
if (lifecycleCallbacks.attributeChangedCallback !== null) {
const observedAttributesIterable = ctor.observedAttributes;
if (observedAttributesIterable !== undefined) {
observedAttributes = convertToSequenceDOMString(observedAttributesIterable);
}
}
let disabledFeatures = [];
const disabledFeaturesIterable = ctor.disabledFeatures;
if (disabledFeaturesIterable) {
disabledFeatures = convertToSequenceDOMString(disabledFeaturesIterable);
}
const formAssociatedValue = ctor.formAssociated;
disableInternals = disabledFeatures.includes("internals");
disableShadow = disabledFeatures.includes("shadow");
formAssociated = webIDLConversions.boolean(formAssociatedValue);
} catch (err) {
caughtError = err;
} finally {
this._elementDefinitionIsRunning = false;
}
if (caughtError !== undefined) {
throw caughtError;
}
const definition = {
name,
localName,
constructor,
objectReference: ctor,
formAssociated,
observedAttributes,
lifecycleCallbacks,
disableShadow,
disableInternals,
constructionStack: []
};
this._customElementDefinitions.push(definition);
const document = idlUtils.implForWrapper(this._globalObject._document);
const upgradeCandidates = [];
for (const candidate of shadowIncludingInclusiveDescendantsIterator(document)) {
if (
(candidate._namespaceURI === HTML_NS && candidate._localName === localName) &&
(extendsOption === null || candidate._isValue === name)
) {
upgradeCandidates.push(candidate);
}
}
for (const upgradeCandidate of upgradeCandidates) {
enqueueCEUpgradeReaction(upgradeCandidate, definition);
}
if (this._whenDefinedPromiseMap[name] !== undefined) {
this._whenDefinedPromiseMap[name].resolve(ctor);
delete this._whenDefinedPromiseMap[name];
}
}
// https://html.spec.whatwg.org/#dom-customelementregistry-get
get(name) {
const definition = this._customElementDefinitions.find(entry => entry.name === name);
return definition && definition.objectReference;
}
// https://html.spec.whatwg.org/#dom-customelementregistry-getname
getName(constructor) {
const found = this._customElementDefinitions.find(entry => entry.objectReference === constructor.objectReference);
return found ? found.name : null;
}
// https://html.spec.whatwg.org/#dom-customelementregistry-whendefined
whenDefined(name) {
if (!isValidCustomElementName(name)) {
return Promise.reject(DOMException.create(
this._globalObject,
["Name argument is not a valid custom element name.", "SyntaxError"]
));
}
const alreadyRegistered = this._customElementDefinitions.find(entry => entry.name === name);
if (alreadyRegistered) {
return Promise.resolve(alreadyRegistered.objectReference);
}
if (this._whenDefinedPromiseMap[name] === undefined) {
let resolve;
const promise = new Promise(r => {
resolve = r;
});
// Store the pending Promise along with the extracted resolve callback to actually resolve the returned Promise,
// once the custom element is registered.
this._whenDefinedPromiseMap[name] = {
promise,
resolve
};
}
return this._whenDefinedPromiseMap[name].promise;
}
// https://html.spec.whatwg.org/#dom-customelementregistry-upgrade
upgrade(root) {
for (const candidate of shadowIncludingInclusiveDescendantsIterator(root)) {
if (candidate.nodeType === NODE_TYPE.ELEMENT_NODE) {
tryUpgradeElement(candidate);
}
}
}
}
module.exports = {
implementation: CustomElementRegistryImpl
};

View File

@@ -0,0 +1,56 @@
"use strict";
const DOMException = require("../generated/DOMException");
const { getLabelsForLabelable } = require("../helpers/form-controls");
class ElementInternalsImpl {
constructor(globalObject, args, { targetElement }) {
this._targetElement = targetElement;
}
get shadowRoot() {
const shadow = this._targetElement._shadowRoot;
if (!shadow || !shadow._availableToElementInternals) {
return null;
}
return shadow;
}
get labels() {
if (!this._targetElement._ceDefinition.formAssociated) {
throw DOMException.create(this._targetElement._globalObject, [
"Accesing an ElementInternal's labels property is only supported for form-associated custom elements",
"NotSupportedError"
]);
}
return getLabelsForLabelable(this._targetElement);
}
// https://html.spec.whatwg.org/#reflecting-content-attributes-in-idl-attributes
_reflectGetTheElement() {
return this._targetElement;
}
_reflectGetTheContentAttribute(reflectedContentAttributeName) {
return this._targetElement._internalContentAttributeMap?.get(reflectedContentAttributeName) ?? null;
}
_reflectSetTheContentAttribute(reflectedContentAttributeName, value) {
if (!this._targetElement._internalContentAttributeMap) {
this._targetElement._internalContentAttributeMap = new Map();
}
this._targetElement._internalContentAttributeMap.set(reflectedContentAttributeName, value);
}
_reflectDeleteTheContentAttribute(reflectedContentAttributeName) {
this._targetElement._internalContentAttributeMap?.delete(reflectedContentAttributeName);
}
}
module.exports = {
implementation: ElementInternalsImpl
};

View File

@@ -0,0 +1,7 @@
"use strict";
class DeviceMotionEventAccelerationImpl {}
module.exports = {
implementation: DeviceMotionEventAccelerationImpl
};

View File

@@ -0,0 +1,7 @@
"use strict";
class DeviceMotionEventRotationRateImpl {}
module.exports = {
implementation: DeviceMotionEventRotationRateImpl
};

15
node_modules/jsdom/lib/jsdom/living/documents.js generated vendored Normal file
View File

@@ -0,0 +1,15 @@
"use strict";
const XMLDocument = require("../living/generated/XMLDocument.js");
const Document = require("../living/generated/Document.js");
const { wrapperForImpl } = require("./generated/utils.js");
exports.createImpl = (globalObject, options, { alwaysUseDocumentClass = false } = {}) => {
if (options.parsingMode === "xml" && !alwaysUseDocumentClass) {
return XMLDocument.createImpl(globalObject, [], { options });
}
return Document.createImpl(globalObject, [], { options });
};
exports.createWrapper = (...args) => {
return wrapperForImpl(exports.createImpl(...args));
};

View File

@@ -0,0 +1,59 @@
"use strict";
const { parseIntoDocument } = require("../../browser/parser");
const idlUtils = require("../generated/utils");
const Document = require("../generated/Document");
exports.implementation = class DOMParserImpl {
constructor(globalObject) {
this._globalObject = globalObject;
}
parseFromString(string, contentType) {
switch (String(contentType)) {
case "text/html": {
return this.createScriptingDisabledDocument("html", contentType, string);
}
case "text/xml":
case "application/xml":
case "application/xhtml+xml":
case "image/svg+xml": {
try {
return this.createScriptingDisabledDocument("xml", contentType, string);
} catch (error) {
const document = this.createScriptingDisabledDocument("xml", contentType);
const element = document.createElementNS("http://www.mozilla.org/newlayout/xml/parsererror.xml", "parsererror");
element.textContent = error.message;
document.appendChild(element);
return document;
}
}
default:
throw new TypeError("Invalid contentType");
}
}
createScriptingDisabledDocument(parsingMode, contentType, string) {
const document = Document.createImpl(this._globalObject, [], {
options: {
parsingMode,
encoding: "UTF-8",
contentType,
readyState: "complete",
scriptingDisabled: true,
url: idlUtils.implForWrapper(this._globalObject._document).URL
}
});
if (string !== undefined) {
parseIntoDocument(string, document);
}
return document;
}
};

View File

@@ -0,0 +1,30 @@
"use strict";
const { parseFragment } = require("../../browser/parser");
const { HTML_NS } = require("../helpers/namespaces.js");
const { isShadowRoot } = require("../helpers/shadow-dom.js");
const NODE_TYPE = require("../node-type.js");
const { fragmentSerialization } = require("./serialization.js");
// https://w3c.github.io/DOM-Parsing/#the-innerhtml-mixin
exports.implementation = class InnerHTMLImpl {
// https://w3c.github.io/DOM-Parsing/#dom-innerhtml-innerhtml
get innerHTML() {
return fragmentSerialization(this, {
outer: false,
requireWellFormed: true,
globalObject: this._globalObject
});
}
set innerHTML(markup) {
const contextElement = isShadowRoot(this) ? this.host : this;
const fragment = parseFragment(markup, contextElement);
let contextObject = this;
if (this.nodeType === NODE_TYPE.ELEMENT_NODE && this.localName === "template" && this.namespaceURI === HTML_NS) {
contextObject = this._templateContents;
}
contextObject._replaceAll(fragment);
}
};

View File

@@ -0,0 +1,18 @@
"use strict";
const serialize = require("w3c-xmlserializer");
const DOMException = require("../generated/DOMException");
const utils = require("../generated/utils");
exports.implementation = class XMLSerializerImpl {
constructor(globalObject) {
this._globalObject = globalObject;
}
serializeToString(root) {
try {
return serialize(utils.wrapperForImpl(root), { requireWellFormed: false });
} catch (e) {
throw DOMException.create(this._globalObject, [e.message, "InvalidStateError"]);
}
}
};

View File

@@ -0,0 +1,63 @@
"use strict";
const nodeTypes = require("../node-type");
const { domSymbolTree } = require("../helpers/internal-constants");
// Serialization only requires a subset of the tree adapter interface.
// Tree traversing
exports.getFirstChild = node => node.firstChild;
exports.getChildNodes = node => domSymbolTree.childrenToArray(node);
exports.getParentNode = node => node.parentNode;
exports.getAttrList = element => {
const attributeList = [...element._attributeList];
if (element._isValue && attributeList.every(attr => attr.name !== "is")) {
attributeList.unshift({
name: "is",
namespace: null,
prefix: null,
value: element._isValue
});
}
return attributeList;
};
// Node data
exports.getTagName = element => element._qualifiedName; // https://github.com/inikulin/parse5/issues/231
exports.getNamespaceURI = element => element.namespaceURI;
exports.getTextNodeContent = exports.getCommentNodeContent = node => node.data;
exports.getDocumentTypeNodeName = node => node.name;
exports.getDocumentTypeNodePublicId = node => node.publicId;
exports.getDocumentTypeNodeSystemId = node => node.systemId;
exports.getTemplateContent = templateElement => templateElement._templateContents;
exports.getDocumentMode = document => document._mode;
// Node types
exports.isTextNode = node => node.nodeType === nodeTypes.TEXT_NODE;
exports.isCommentNode = node => node.nodeType === nodeTypes.COMMENT_NODE;
exports.isDocumentTypeNode = node => node.nodeType === nodeTypes.DOCUMENT_TYPE_NODE;
exports.isElementNode = node => node.nodeType === nodeTypes.ELEMENT_NODE;
// Source code location
exports.setNodeSourceCodeLocation = (node, location) => {
node.sourceCodeLocation = location;
};
exports.getNodeSourceCodeLocation = node => node.sourceCodeLocation;
exports.updateNodeSourceCodeLocation = (node, endLocation) => {
Object.assign(node.sourceCodeLocation, endLocation);
};

View File

@@ -0,0 +1,36 @@
"use strict";
const produceXMLSerialization = require("w3c-xmlserializer");
const parse5 = require("parse5");
const DOMException = require("../generated/DOMException");
const { domSymbolTree } = require("../helpers/internal-constants");
const utils = require("../generated/utils");
const treeAdapter = require("./parse5-adapter-serialization");
const NODE_TYPE = require("../node-type");
module.exports.fragmentSerialization = (node, { outer, requireWellFormed, globalObject }) => {
const contextDocument =
node.nodeType === NODE_TYPE.DOCUMENT_NODE ? node : node._ownerDocument;
if (contextDocument._parsingMode === "html") {
const config = {
...contextDocument._parseOptions,
treeAdapter
};
return outer ? parse5.serializeOuter(node, config) : parse5.serialize(node, config);
}
const childNodes = outer ? [node] : domSymbolTree.childrenToArray(node);
try {
let serialized = "";
for (let i = 0; i < childNodes.length; ++i) {
serialized += produceXMLSerialization(
utils.wrapperForImpl(childNodes[i]),
{ requireWellFormed }
);
}
return serialized;
} catch (e) {
throw DOMException.create(globalObject, [e.message, "InvalidStateError"]);
}
};

View File

@@ -0,0 +1,25 @@
"use strict";
const { TextDecoder } = require("@exodus/bytes/encoding.js");
// A thin wrapper is needed since there are constructor arguments, which mismatches webidl2js's assumed pattern.
exports.implementation = class TextDecoderImpl {
constructor(globalObject, [label, options]) {
this._innerImpl = new TextDecoder(label, options);
}
decode(input, options) {
return this._innerImpl.decode(input, options);
}
get encoding() {
return this._innerImpl.encoding;
}
get fatal() {
return this._innerImpl.fatal;
}
get ignoreBOM() {
return this._innerImpl.ignoreBOM;
}
};

View File

@@ -0,0 +1,5 @@
"use strict";
const { TextEncoder } = require("@exodus/bytes/encoding.js");
// No wrapper needed since there are no constructor arguments.
exports.implementation = TextEncoder;

View File

@@ -0,0 +1,12 @@
"use strict";
const EventImpl = require("./Event-impl").implementation;
const EventInit = require("../generated/EventInit");
class BeforeUnloadEventImpl extends EventImpl {}
BeforeUnloadEventImpl.defaultInit = EventInit.convert(undefined, undefined);
module.exports = {
implementation: BeforeUnloadEventImpl
};

View File

@@ -0,0 +1,14 @@
"use strict";
const EventImpl = require("./Event-impl").implementation;
class BlobEventImpl extends EventImpl {}
// Cannot use the usual pattern since `data` is required.
BlobEventImpl.defaultInit = {
__proto__: null,
timecode: 0
};
module.exports = {
implementation: BlobEventImpl
};

View File

@@ -0,0 +1,10 @@
"use strict";
const EventImpl = require("./Event-impl").implementation;
const CloseEventInit = require("../generated/CloseEventInit");
class CloseEventImpl extends EventImpl {}
CloseEventImpl.defaultInit = CloseEventInit.convert(undefined, undefined);
exports.implementation = CloseEventImpl;

View File

@@ -0,0 +1,20 @@
"use strict";
const UIEventImpl = require("./UIEvent-impl").implementation;
const CompositionEventInit = require("../generated/CompositionEventInit");
class CompositionEventImpl extends UIEventImpl {
initCompositionEvent(type, bubbles, cancelable, view, data) {
if (this._dispatchFlag) {
return;
}
this.initUIEvent(type, bubbles, cancelable, view, 0);
this.data = data;
}
}
CompositionEventImpl.defaultInit = CompositionEventInit.convert(undefined, undefined);
module.exports = {
implementation: CompositionEventImpl
};

View File

@@ -0,0 +1,21 @@
"use strict";
const EventImpl = require("./Event-impl").implementation;
const CustomEventInit = require("../generated/CustomEventInit");
class CustomEventImpl extends EventImpl {
initCustomEvent(type, bubbles, cancelable, detail) {
if (this._dispatchFlag) {
return;
}
this.initEvent(type, bubbles, cancelable);
this.detail = detail;
}
}
CustomEventImpl.defaultInit = CustomEventInit.convert(undefined, undefined);
module.exports = {
implementation: CustomEventImpl
};

View File

@@ -0,0 +1,49 @@
"use strict";
const EventImpl = require("./Event-impl").implementation;
const { implementation: DeviceMotionEventAccelerationImpl } =
require("../deviceorientation/DeviceMotionEventAcceleration-impl");
const { implementation: DeviceMotionEventRotationRateImpl } =
require("../deviceorientation/DeviceMotionEventRotationRate-impl");
class DeviceMotionEventImpl extends EventImpl {
constructor(globalObject, args, privateData) {
super(globalObject, args, privateData);
const eventInitDict = args[1];
this.acceleration = null;
if (eventInitDict?.acceleration) {
const accelImpl = new DeviceMotionEventAccelerationImpl(globalObject, [], {});
accelImpl.x = eventInitDict.acceleration.x;
accelImpl.y = eventInitDict.acceleration.y;
accelImpl.z = eventInitDict.acceleration.z;
this.acceleration = accelImpl;
}
this.accelerationIncludingGravity = null;
if (eventInitDict?.accelerationIncludingGravity) {
const accelGImpl = new DeviceMotionEventAccelerationImpl(globalObject, [], {});
accelGImpl.x = eventInitDict.accelerationIncludingGravity.x;
accelGImpl.y = eventInitDict.accelerationIncludingGravity.y;
accelGImpl.z = eventInitDict.accelerationIncludingGravity.z;
this.accelerationIncludingGravity = accelGImpl;
}
this.rotationRate = null;
if (eventInitDict?.rotationRate) {
const rotImpl = new DeviceMotionEventRotationRateImpl(globalObject, [], {});
rotImpl.alpha = eventInitDict.rotationRate.alpha;
rotImpl.beta = eventInitDict.rotationRate.beta;
rotImpl.gamma = eventInitDict.rotationRate.gamma;
this.rotationRate = rotImpl;
}
this.interval = eventInitDict?.interval ?? 0;
}
}
DeviceMotionEventImpl.defaultInit = Object.create(null);
module.exports = {
implementation: DeviceMotionEventImpl
};

View File

@@ -0,0 +1,10 @@
"use strict";
const EventImpl = require("./Event-impl").implementation;
const DeviceOrientationEventInit = require("../generated/DeviceOrientationEventInit");
class DeviceOrientationEventImpl extends EventImpl {}
DeviceOrientationEventImpl.defaultInit = DeviceOrientationEventInit.convert(undefined, undefined);
module.exports = {
implementation: DeviceOrientationEventImpl
};

View File

@@ -0,0 +1,14 @@
"use strict";
const EventImpl = require("./Event-impl").implementation;
const ErrorEventInit = require("../generated/ErrorEventInit");
class ErrorEventImpl extends EventImpl {
}
ErrorEventImpl.defaultInit = ErrorEventInit.convert(undefined, undefined);
module.exports = {
implementation: ErrorEventImpl
};

View File

@@ -0,0 +1,195 @@
"use strict";
const idlUtils = require("../generated/utils");
const EventInit = require("../generated/EventInit");
class EventImpl {
constructor(globalObject, args, privateData) {
const [type, eventInitDict = this.constructor.defaultInit] = args;
this.type = type;
this.bubbles = false;
this.cancelable = false;
for (const key in eventInitDict) {
this[key] = eventInitDict[key];
}
for (const key in this.constructor.defaultInit) {
if (!(key in eventInitDict)) {
this[key] = this.constructor.defaultInit[key];
}
}
this.target = null;
this.currentTarget = null;
this.eventPhase = 0;
this._globalObject = globalObject;
this._initializedFlag = true;
this._stopPropagationFlag = false;
this._stopImmediatePropagationFlag = false;
this._canceledFlag = false;
this._inPassiveListenerFlag = false;
this._dispatchFlag = false;
this._path = [];
this.isTrusted = privateData.isTrusted || false;
this.timeStamp = Date.now();
}
// https://dom.spec.whatwg.org/#set-the-canceled-flag
_setTheCanceledFlag() {
if (this.cancelable && !this._inPassiveListenerFlag) {
this._canceledFlag = true;
}
}
get srcElement() {
return this.target;
}
get returnValue() {
return !this._canceledFlag;
}
set returnValue(v) {
if (v === false) {
this._setTheCanceledFlag();
}
}
get defaultPrevented() {
return this._canceledFlag;
}
stopPropagation() {
this._stopPropagationFlag = true;
}
get cancelBubble() {
return this._stopPropagationFlag;
}
set cancelBubble(v) {
if (v) {
this._stopPropagationFlag = true;
}
}
stopImmediatePropagation() {
this._stopPropagationFlag = true;
this._stopImmediatePropagationFlag = true;
}
preventDefault() {
this._setTheCanceledFlag();
}
// https://dom.spec.whatwg.org/#dom-event-composedpath
// Current implementation is based of https://whatpr.org/dom/699.html#dom-event-composedpath
// due to a bug in composed path implementation https://github.com/whatwg/dom/issues/684
composedPath() {
const composedPath = [];
const { currentTarget, _path: path } = this;
if (path.length === 0) {
return composedPath;
}
composedPath.push(currentTarget);
let currentTargetIndex = 0;
let currentTargetHiddenSubtreeLevel = 0;
for (let index = path.length - 1; index >= 0; index--) {
const { item, rootOfClosedTree, slotInClosedTree } = path[index];
if (rootOfClosedTree) {
currentTargetHiddenSubtreeLevel++;
}
if (item === idlUtils.implForWrapper(currentTarget)) {
currentTargetIndex = index;
break;
}
if (slotInClosedTree) {
currentTargetHiddenSubtreeLevel--;
}
}
let currentHiddenLevel = currentTargetHiddenSubtreeLevel;
let maxHiddenLevel = currentTargetHiddenSubtreeLevel;
for (let i = currentTargetIndex - 1; i >= 0; i--) {
const { item, rootOfClosedTree, slotInClosedTree } = path[i];
if (rootOfClosedTree) {
currentHiddenLevel++;
}
if (currentHiddenLevel <= maxHiddenLevel) {
composedPath.unshift(idlUtils.wrapperForImpl(item));
}
if (slotInClosedTree) {
currentHiddenLevel--;
if (currentHiddenLevel < maxHiddenLevel) {
maxHiddenLevel = currentHiddenLevel;
}
}
}
currentHiddenLevel = currentTargetHiddenSubtreeLevel;
maxHiddenLevel = currentTargetHiddenSubtreeLevel;
for (let index = currentTargetIndex + 1; index < path.length; index++) {
const { item, rootOfClosedTree, slotInClosedTree } = path[index];
if (slotInClosedTree) {
currentHiddenLevel++;
}
if (currentHiddenLevel <= maxHiddenLevel) {
composedPath.push(idlUtils.wrapperForImpl(item));
}
if (rootOfClosedTree) {
currentHiddenLevel--;
if (currentHiddenLevel < maxHiddenLevel) {
maxHiddenLevel = currentHiddenLevel;
}
}
}
return composedPath;
}
_initialize(type, bubbles, cancelable) {
this.type = type;
this._initializedFlag = true;
this._stopPropagationFlag = false;
this._stopImmediatePropagationFlag = false;
this._canceledFlag = false;
this.isTrusted = false;
this.target = null;
this.bubbles = bubbles;
this.cancelable = cancelable;
}
initEvent(type, bubbles, cancelable) {
if (this._dispatchFlag) {
return;
}
this._initialize(type, bubbles, cancelable);
}
}
EventImpl.defaultInit = EventInit.convert(undefined, undefined);
module.exports = {
implementation: EventImpl
};

View File

@@ -0,0 +1,24 @@
"use strict";
// This mixin doesn't have an IDL equivalent, but since MouseEvent and KeyboardEvent implement getModifierState() the
// same way, its implementation is shared here.
class EventModifierMixinImpl {
// Event's constructor assumes all options correspond to IDL attributes with the same names, and sets them on `this`.
// That is not the case for these modifier boolean options, but since the options are set on `this` anyway we'll
// access them that way. The spec doesn't say much about the case where keyArg is not one of the valid ones
// (https://w3c.github.io/uievents-key/#keys-modifier), but at least Chrome returns false for invalid modifiers. Since
// these invalid modifiers will be undefined on `this` (thus `false` after casting it to boolean), we don't need to do
// extra checking for validity.
getModifierState(keyArg) {
if (keyArg === "Control") {
return Boolean(this.ctrlKey);
}
if (["Alt", "Meta", "Shift"].includes(keyArg)) {
return Boolean(this[`${keyArg.toLowerCase()}Key`]);
}
return Boolean(this[`modifier${keyArg}`]);
}
}
exports.implementation = EventModifierMixinImpl;

View File

@@ -0,0 +1,438 @@
"use strict";
const DOMException = require("../generated/DOMException");
const isWindow = require("../helpers/is-window");
const reportException = require("../helpers/runtime-script-errors");
const idlUtils = require("../generated/utils");
const { nodeRoot } = require("../helpers/node");
const {
isNode, isShadowRoot, isSlotable, getEventTargetParent,
isShadowInclusiveAncestor, retarget
} = require("../helpers/shadow-dom");
const MouseEvent = require("../generated/MouseEvent");
const EVENT_PHASE = {
NONE: 0,
CAPTURING_PHASE: 1,
AT_TARGET: 2,
BUBBLING_PHASE: 3
};
class EventTargetImpl {
constructor(globalObject) {
this._globalObject = globalObject;
this._eventListeners = Object.create(null);
}
// Default argument is necessary because webidl2js cannot handle `= {}` with unions at the moment.
addEventListener(type, callback, options = { __proto__: null, capture: false, once: false }) {
let { capture, once, passive, signal } = flattenMoreEventListenerOptions(options);
if (signal !== null && signal.aborted) {
return;
}
if (callback === null) {
return;
}
if (passive === null) {
passive = defaultPassiveValue(type, this);
}
if (!this._eventListeners[type]) {
this._eventListeners[type] = [];
}
for (let i = 0; i < this._eventListeners[type].length; ++i) {
const listener = this._eventListeners[type][i];
if (
listener.callback.objectReference === callback.objectReference &&
listener.capture === capture
) {
return;
}
}
this._eventListeners[type].push({
callback,
capture,
once,
passive,
signal
});
if (signal !== null) {
signal._addAlgorithm(() => {
this.removeEventListener(type, callback, options);
});
}
}
// Default argument is necessary because webidl2js cannot handle `= {}` with unions at the moment.
removeEventListener(type, callback, options = { __proto__: null, capture: false }) {
const capture = flattenEventListenerOptions(options);
if (callback === null) {
// Optimization, not in the spec.
return;
}
if (!this._eventListeners[type]) {
return;
}
for (let i = 0; i < this._eventListeners[type].length; ++i) {
const listener = this._eventListeners[type][i];
if (
listener.callback.objectReference === callback.objectReference &&
listener.capture === capture
) {
this._eventListeners[type].splice(i, 1);
break;
}
}
}
dispatchEvent(eventImpl) {
if (eventImpl._dispatchFlag || !eventImpl._initializedFlag) {
throw DOMException.create(this._globalObject, [
"Tried to dispatch an uninitialized event",
"InvalidStateError"
]);
}
if (eventImpl.eventPhase !== EVENT_PHASE.NONE) {
throw DOMException.create(this._globalObject, [
"Tried to dispatch a dispatching event",
"InvalidStateError"
]);
}
eventImpl.isTrusted = false;
return this._dispatch(eventImpl);
}
// https://dom.spec.whatwg.org/#get-the-parent
_getTheParent() {
return null;
}
// https://dom.spec.whatwg.org/#concept-event-dispatch
// legacyOutputDidListenersThrowFlag optional parameter is not necessary here since it is only used by indexDB.
_dispatch(eventImpl, legacyTargetOverrideFlag /* , legacyOutputDidListenersThrowFlag */) {
let targetImpl = this;
let clearTargets = false;
let activationTarget = null;
eventImpl._dispatchFlag = true;
const targetOverride = legacyTargetOverrideFlag ?
idlUtils.implForWrapper(targetImpl._globalObject._document) :
targetImpl;
let relatedTarget = retarget(eventImpl.relatedTarget, targetImpl);
if (targetImpl !== relatedTarget || targetImpl === eventImpl.relatedTarget) {
const touchTargets = [];
appendToEventPath(eventImpl, targetImpl, targetOverride, relatedTarget, touchTargets, false);
const isActivationEvent = MouseEvent.isImpl(eventImpl) && eventImpl.type === "click";
if (isActivationEvent && targetImpl._hasActivationBehavior) {
activationTarget = targetImpl;
}
let slotInClosedTree = false;
let slotable = isSlotable(targetImpl) && targetImpl._assignedSlot ? targetImpl : null;
let parent = getEventTargetParent(targetImpl, eventImpl);
// Populate event path
// https://dom.spec.whatwg.org/#event-path
while (parent !== null) {
if (slotable !== null) {
if (parent.localName !== "slot") {
throw new Error(`JSDOM Internal Error: Expected parent to be a Slot`);
}
slotable = null;
const parentRoot = nodeRoot(parent);
if (isShadowRoot(parentRoot) && parentRoot.mode === "closed") {
slotInClosedTree = true;
}
}
if (isSlotable(parent) && parent._assignedSlot) {
slotable = parent;
}
relatedTarget = retarget(eventImpl.relatedTarget, parent);
if (
(isNode(parent) && isShadowInclusiveAncestor(nodeRoot(targetImpl), parent)) ||
idlUtils.wrapperForImpl(parent).constructor.name === "Window"
) {
if (isActivationEvent && eventImpl.bubbles && activationTarget === null &&
parent._hasActivationBehavior) {
activationTarget = parent;
}
appendToEventPath(eventImpl, parent, null, relatedTarget, touchTargets, slotInClosedTree);
} else if (parent === relatedTarget) {
parent = null;
} else {
targetImpl = parent;
if (isActivationEvent && activationTarget === null && targetImpl._hasActivationBehavior) {
activationTarget = targetImpl;
}
appendToEventPath(eventImpl, parent, targetImpl, relatedTarget, touchTargets, slotInClosedTree);
}
if (parent !== null) {
parent = getEventTargetParent(parent, eventImpl);
}
slotInClosedTree = false;
}
let clearTargetsStructIndex = -1;
for (let i = eventImpl._path.length - 1; i >= 0 && clearTargetsStructIndex === -1; i--) {
if (eventImpl._path[i].target !== null) {
clearTargetsStructIndex = i;
}
}
const clearTargetsStruct = eventImpl._path[clearTargetsStructIndex];
clearTargets =
(isNode(clearTargetsStruct.target) && isShadowRoot(nodeRoot(clearTargetsStruct.target))) ||
(isNode(clearTargetsStruct.relatedTarget) && isShadowRoot(nodeRoot(clearTargetsStruct.relatedTarget)));
if (activationTarget !== null && activationTarget._legacyPreActivationBehavior) {
activationTarget._legacyPreActivationBehavior();
}
for (let i = eventImpl._path.length - 1; i >= 0; --i) {
const struct = eventImpl._path[i];
if (struct.target !== null) {
eventImpl.eventPhase = EVENT_PHASE.AT_TARGET;
} else {
eventImpl.eventPhase = EVENT_PHASE.CAPTURING_PHASE;
}
invokeEventListeners(struct, eventImpl, "capturing");
}
for (let i = 0; i < eventImpl._path.length; i++) {
const struct = eventImpl._path[i];
if (struct.target !== null) {
eventImpl.eventPhase = EVENT_PHASE.AT_TARGET;
} else {
if (!eventImpl.bubbles) {
continue;
}
eventImpl.eventPhase = EVENT_PHASE.BUBBLING_PHASE;
}
invokeEventListeners(struct, eventImpl, "bubbling");
}
}
eventImpl.eventPhase = EVENT_PHASE.NONE;
eventImpl.currentTarget = null;
eventImpl._path = [];
eventImpl._dispatchFlag = false;
eventImpl._stopPropagationFlag = false;
eventImpl._stopImmediatePropagationFlag = false;
if (clearTargets) {
eventImpl.target = null;
eventImpl.relatedTarget = null;
}
if (activationTarget !== null) {
if (!eventImpl._canceledFlag) {
activationTarget._activationBehavior(eventImpl);
} else if (activationTarget._legacyCanceledActivationBehavior) {
activationTarget._legacyCanceledActivationBehavior();
}
}
return !eventImpl._canceledFlag;
}
}
module.exports = {
implementation: EventTargetImpl
};
// https://dom.spec.whatwg.org/#concept-event-listener-invoke
function invokeEventListeners(struct, eventImpl, phase) {
const structIndex = eventImpl._path.indexOf(struct);
for (let i = structIndex; i >= 0; i--) {
const t = eventImpl._path[i];
if (t.target) {
eventImpl.target = t.target;
break;
}
}
eventImpl.relatedTarget = idlUtils.wrapperForImpl(struct.relatedTarget);
if (eventImpl._stopPropagationFlag) {
return;
}
eventImpl.currentTarget = idlUtils.wrapperForImpl(struct.item);
const listeners = struct.item._eventListeners;
innerInvokeEventListeners(eventImpl, listeners, phase, struct.itemInShadowTree);
}
// https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke
function innerInvokeEventListeners(eventImpl, listeners, phase, itemInShadowTree) {
let found = false;
const { type, target } = eventImpl;
const wrapper = idlUtils.wrapperForImpl(target);
if (!listeners || !listeners[type]) {
return found;
}
// Copy event listeners before iterating since the list can be modified during the iteration.
const handlers = listeners[type].slice();
for (let i = 0; i < handlers.length; i++) {
const listener = handlers[i];
const { callback, capture, once, passive } = listener;
// Check if the event listener has been removed since the listeners has been cloned.
if (!listeners[type].includes(listener)) {
continue;
}
found = true;
if (
(phase === "capturing" && !capture) ||
(phase === "bubbling" && capture)
) {
continue;
}
if (once) {
listeners[type].splice(listeners[type].indexOf(listener), 1);
}
let window = null;
if (wrapper && wrapper._document) {
// Triggered by Window
window = wrapper;
} else if (target._ownerDocument) {
// Triggered by most webidl2js'ed instances
window = target._ownerDocument._defaultView;
} else if (wrapper._ownerDocument) {
// Currently triggered by some non-webidl2js things
window = wrapper._ownerDocument._defaultView;
}
let currentEvent;
if (window) {
currentEvent = window._currentEvent;
if (!itemInShadowTree) {
window._currentEvent = eventImpl;
}
}
if (passive) {
eventImpl._inPassiveListenerFlag = true;
}
try {
callback.call(eventImpl.currentTarget, eventImpl);
} catch (e) {
if (window) {
reportException(window, e);
}
// Errors in window-less documents just get swallowed... can you think of anything better?
}
eventImpl._inPassiveListenerFlag = false;
if (window) {
window._currentEvent = currentEvent;
}
if (eventImpl._stopImmediatePropagationFlag) {
return found;
}
}
return found;
}
function flattenMoreEventListenerOptions(options) {
const dict = {
capture: flattenEventListenerOptions(options),
once: false,
passive: null,
signal: null
};
if (options !== null && typeof options === "object") {
dict.once = options.once;
if ("passive" in options) {
dict.passive = options.passive;
}
if ("signal" in options) {
dict.signal = options.signal;
}
}
return dict;
}
function flattenEventListenerOptions(options) {
if (typeof options === "boolean") {
return options;
}
return options.capture;
}
function defaultPassiveValue(type, eventTarget) {
switch (type) {
case "touchstart":
case "touchmove":
case "wheel":
case "mousewheel":
return isWindow(eventTarget) ||
eventTarget._ownerDocument === eventTarget ||
eventTarget._ownerDocument.documentElement === eventTarget ||
eventTarget._ownerDocument.body === eventTarget;
default:
return false;
}
}
// https://dom.spec.whatwg.org/#concept-event-path-append
function appendToEventPath(eventImpl, target, targetOverride, relatedTarget, touchTargets, slotInClosedTree) {
const itemInShadowTree = isNode(target) && isShadowRoot(nodeRoot(target));
const rootOfClosedTree = isShadowRoot(target) && target.mode === "closed";
eventImpl._path.push({
item: target,
itemInShadowTree,
target: targetOverride,
relatedTarget,
touchTargets,
rootOfClosedTree,
slotInClosedTree
});
}

View File

@@ -0,0 +1,9 @@
"use strict";
const UIEventImpl = require("./UIEvent-impl").implementation;
const FocusEventInit = require("../generated/FocusEventInit");
class FocusEventImpl extends UIEventImpl {}
FocusEventImpl.defaultInit = FocusEventInit.convert(undefined, undefined);
exports.implementation = FocusEventImpl;

View File

@@ -0,0 +1,14 @@
"use strict";
const EventImpl = require("./Event-impl").implementation;
const HashChangeEventInit = require("../generated/HashChangeEventInit");
class HashChangeEventImpl extends EventImpl {
}
HashChangeEventImpl.defaultInit = HashChangeEventInit.convert(undefined, undefined);
module.exports = {
implementation: HashChangeEventImpl
};

View File

@@ -0,0 +1,11 @@
"use strict";
const UIEventImpl = require("./UIEvent-impl").implementation;
const InputEventInit = require("../generated/InputEventInit");
// https://w3c.github.io/uievents/#interface-inputevent
class InputEventImpl extends UIEventImpl { }
InputEventImpl.defaultInit = InputEventInit.convert(undefined, undefined);
module.exports = {
implementation: InputEventImpl
};

View File

@@ -0,0 +1,29 @@
"use strict";
const { mixin } = require("../../utils");
const EventModifierMixinImpl = require("./EventModifierMixin-impl").implementation;
const UIEventImpl = require("./UIEvent-impl").implementation;
const KeyboardEventInit = require("../generated/KeyboardEventInit");
class KeyboardEventImpl extends UIEventImpl {
initKeyboardEvent(type, bubbles, cancelable, view, key, location, ctrlKey, altKey, shiftKey, metaKey) {
if (this._dispatchFlag) {
return;
}
this.initUIEvent(type, bubbles, cancelable, view, 0);
this.key = key;
this.location = location;
this.ctrlKey = ctrlKey;
this.altKey = altKey;
this.shiftKey = shiftKey;
this.metaKey = metaKey;
}
}
mixin(KeyboardEventImpl.prototype, EventModifierMixinImpl.prototype);
KeyboardEventImpl.defaultInit = KeyboardEventInit.convert(undefined, undefined);
module.exports = {
implementation: KeyboardEventImpl
};

View File

@@ -0,0 +1,25 @@
"use strict";
const EventImpl = require("./Event-impl").implementation;
const MessageEventInit = require("../generated/MessageEventInit");
class MessageEventImpl extends EventImpl {
initMessageEvent(type, bubbles, cancelable, data, origin, lastEventId, source, ports) {
if (this._dispatchFlag) {
return;
}
this.initEvent(type, bubbles, cancelable);
this.data = data;
this.origin = origin;
this.lastEventId = lastEventId;
this.source = source;
this.ports = ports;
}
}
MessageEventImpl.defaultInit = MessageEventInit.convert(undefined, undefined);
module.exports = {
implementation: MessageEventImpl
};

View File

@@ -0,0 +1,72 @@
"use strict";
const { mixin } = require("../../utils");
const EventModifierMixinImpl = require("./EventModifierMixin-impl").implementation;
const UIEventImpl = require("./UIEvent-impl").implementation;
const MouseEventInit = require("../generated/MouseEventInit");
class MouseEventImpl extends UIEventImpl {
get x() {
return this.clientX;
}
get y() {
return this.clientY;
}
get pageX() {
// TODO: consider dispatch flag and return page-relative event coordinate once layout is supported
return this.clientX; // TODO: add horizontal scroll offset once jsdom implements scrolling support
}
get pageY() {
// TODO: consider dispatch flag and return page-relative event coordinate once layout is supported
return this.clientY; // TODO: add vertical scroll offset once jsdom implements scrolling support
}
get offsetX() {
// TODO: consider dispatch flag and return target-relative event coordinate once layout is supported
return this.pageX;
}
get offsetY() {
// TODO: consider dispatch flag and return target-relative event coordinate once layout is supported
return this.pageY;
}
initMouseEvent(
type,
bubbles,
cancelable,
view,
detail,
screenX,
screenY,
clientX,
clientY,
ctrlKey,
altKey,
shiftKey,
metaKey,
button,
relatedTarget
) {
if (this._dispatchFlag) {
return;
}
this.initUIEvent(type, bubbles, cancelable, view, detail);
this.screenX = screenX;
this.screenY = screenY;
this.clientX = clientX;
this.clientY = clientY;
this.ctrlKey = ctrlKey;
this.altKey = altKey;
this.shiftKey = shiftKey;
this.metaKey = metaKey;
this.button = button;
this.relatedTarget = relatedTarget;
}
}
mixin(MouseEventImpl.prototype, EventModifierMixinImpl.prototype);
MouseEventImpl.defaultInit = MouseEventInit.convert(undefined, undefined);
module.exports = {
implementation: MouseEventImpl
};

View File

@@ -0,0 +1,20 @@
"use strict";
const EventImpl = require("./Event-impl").implementation;
const PageTransitionEventInit = require("../generated/PageTransitionEventInit");
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#pagetransitionevent
class PageTransitionEventImpl extends EventImpl {
initPageTransitionEvent(type, bubbles, cancelable, persisted) {
if (this._dispatchFlag) {
return;
}
this.initEvent(type, bubbles, cancelable);
this.persisted = persisted;
}
}
PageTransitionEventImpl.defaultInit = PageTransitionEventInit.convert(undefined, undefined);
exports.implementation = PageTransitionEventImpl;

View File

@@ -0,0 +1,21 @@
"use strict";
const MouseEventImpl = require("./MouseEvent-impl").implementation;
const PointerEventInit = require("../generated/PointerEventInit");
class PointerEventImpl extends MouseEventImpl {
getCoalescedEvents() {
// The EventImpl constructor initializes this.coalescedEvents from the init dictionary.
// Return a new array each time (webidl2js doesn't handle this for us.)
return [...this.coalescedEvents];
}
getPredictedEvents() {
// As above.
return [...this.predictedEvents];
}
}
PointerEventImpl.defaultInit = PointerEventInit.convert(undefined, undefined);
module.exports = {
implementation: PointerEventImpl
};

View File

@@ -0,0 +1,9 @@
"use strict";
const EventImpl = require("./Event-impl.js").implementation;
const PopStateEventInit = require("../generated/PopStateEventInit");
class PopStateEventImpl extends EventImpl {}
PopStateEventImpl.defaultInit = PopStateEventInit.convert(undefined, undefined);
exports.implementation = PopStateEventImpl;

View File

@@ -0,0 +1,14 @@
"use strict";
const EventImpl = require("./Event-impl").implementation;
const ProgressEventInit = require("../generated/ProgressEventInit");
class ProgressEventImpl extends EventImpl {
}
ProgressEventImpl.defaultInit = ProgressEventInit.convert(undefined, undefined);
module.exports = {
implementation: ProgressEventImpl
};

View File

@@ -0,0 +1,14 @@
"use strict";
const EventImpl = require("./Event-impl").implementation;
class PromiseRejectionEventImpl extends EventImpl {}
// Cannot use the usual pattern because `promise` is required.
PromiseRejectionEventImpl.defaultInit = {
__proto__: null,
reason: undefined
};
module.exports = {
implementation: PromiseRejectionEventImpl
};

View File

@@ -0,0 +1,26 @@
"use strict";
const EventImpl = require("./Event-impl").implementation;
const StorageEventInit = require("../generated/StorageEventInit");
// https://html.spec.whatwg.org/multipage/webstorage.html#the-storageevent-interface
class StorageEventImpl extends EventImpl {
initStorageEvent(type, bubbles, cancelable, key, oldValue, newValue, url, storageArea) {
if (this._dispatchFlag) {
return;
}
this.initEvent(type, bubbles, cancelable);
this.key = key;
this.oldValue = oldValue;
this.newValue = newValue;
this.url = url;
this.storageArea = storageArea;
}
}
StorageEventImpl.defaultInit = StorageEventInit.convert(undefined, undefined);
module.exports = {
implementation: StorageEventImpl
};

View File

@@ -0,0 +1,13 @@
"use strict";
const EventImpl = require("./Event-impl").implementation;
const SubmitEventInit = require("../generated/SubmitEventInit");
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#the-submitevent-interface
class SubmitEventImpl extends EventImpl {}
SubmitEventImpl.defaultInit = SubmitEventInit.convert(undefined, undefined);
module.exports = {
implementation: SubmitEventImpl
};

View File

@@ -0,0 +1,14 @@
"use strict";
const UIEventImpl = require("./UIEvent-impl").implementation;
const TouchEventInit = require("../generated/TouchEventInit");
class TouchEventImpl extends UIEventImpl {
}
TouchEventImpl.defaultInit = TouchEventInit.convert(undefined, undefined);
module.exports = {
implementation: TouchEventImpl
};

View File

@@ -0,0 +1,10 @@
"use strict";
const EventImpl = require("./Event-impl").implementation;
const TransitionEventInit = require("../generated/TransitionEventInit");
class TransitionEventImpl extends EventImpl {}
TransitionEventImpl.defaultInit = TransitionEventInit.convert(undefined, undefined);
module.exports = {
implementation: TransitionEventImpl
};

View File

@@ -0,0 +1,43 @@
"use strict";
const isWindow = require("../helpers/is-window");
const UIEventInit = require("../generated/UIEventInit");
const EventImpl = require("./Event-impl").implementation;
class UIEventImpl extends EventImpl {
constructor(globalObject, args, privateData) {
const eventInitDict = args[1];
// undefined check included so that we can omit the property in internal usage.
if (eventInitDict && eventInitDict.view !== null && eventInitDict.view !== undefined) {
if (!isWindow(eventInitDict.view)) {
throw new TypeError(`Failed to construct '${new.target.name.replace(/Impl$/, "")}': member view is not of ` +
"type Window.");
}
}
super(globalObject, args, privateData);
}
initUIEvent(type, bubbles, cancelable, view, detail) {
if (view !== null) {
if (!isWindow(view)) {
throw new TypeError(`Failed to execute 'initUIEvent' on '${this.constructor.name.replace(/Impl$/, "")}': ` +
"parameter 4 is not of type 'Window'.");
}
}
if (this._dispatchFlag) {
return;
}
this.initEvent(type, bubbles, cancelable);
this.view = view;
this.detail = detail;
}
}
UIEventImpl.defaultInit = UIEventInit.convert(undefined, undefined);
module.exports = {
implementation: UIEventImpl
};

View File

@@ -0,0 +1,12 @@
"use strict";
const MouseEventImpl = require("./MouseEvent-impl").implementation;
const WheelEventInit = require("../generated/WheelEventInit");
class WheelEventImpl extends MouseEventImpl {}
WheelEventImpl.defaultInit = WheelEventInit.convert(undefined, undefined);
module.exports = {
implementation: WheelEventImpl
};

View File

@@ -0,0 +1,173 @@
"use strict";
const {
isForbiddenRequestHeader,
isForbiddenResponseHeaderName,
isPrivilegedNoCORSRequestHeaderName,
isNoCORSSafelistedRequestHeaderName,
isNoCORSSafelistedRequestHeader
} = require("./header-types");
const { isHeaderName, isHeaderValue, normalizeHeaderValue } = require("./header-utils");
const HeaderList = require("./header-list");
function assertName(name) {
if (!isHeaderName(name)) {
throw new TypeError("name is invalid");
}
}
function assertValue(value) {
if (!isHeaderValue(value)) {
throw new TypeError("value is invalid");
}
}
class HeadersImpl {
constructor(globalObject, args) {
this.guard = "none";
this.headerList = new HeaderList();
if (args[0]) {
this.#fill(args[0]);
}
}
// https://fetch.spec.whatwg.org/#headers-validate
#validate(name, value) {
assertName(name);
assertValue(value);
switch (this.guard) {
case "immutable": {
throw new TypeError("Headers is immutable");
}
case "request": {
if (isForbiddenRequestHeader(name, value)) {
return false;
}
break;
}
case "response": {
if (isForbiddenResponseHeaderName(name)) {
return false;
}
break;
}
}
return true;
}
// https://fetch.spec.whatwg.org/#concept-headers-fill
#fill(init) {
if (Array.isArray(init)) {
for (const header of init) {
if (header.length !== 2) {
throw new TypeError("init is invalid");
}
this.append(header[0], header[1]);
}
} else {
for (const [key, value] of Object.entries(init)) {
this.append(key, value);
}
}
}
// https://fetch.spec.whatwg.org/#concept-headers-remove-privileged-no-cors-request-headers
#removePrivilegedNoCORSHeaders() {
this.headerList.delete("range");
}
// https://fetch.spec.whatwg.org/#dom-headers-append
append(name, value) {
value = normalizeHeaderValue(value);
if (!this.#validate(name, value)) {
return;
}
if (this.guard === "request-no-cors") {
let temporaryValue = this.headerList.get(name);
if (temporaryValue === null) {
temporaryValue = value;
} else {
temporaryValue += ", " + value;
}
if (!isNoCORSSafelistedRequestHeader(name, temporaryValue)) {
return;
}
}
this.headerList.append(name, value);
if (this.guard === "request-no-cors") {
this.#removePrivilegedNoCORSHeaders();
}
}
// https://fetch.spec.whatwg.org/#dom-headers-delete
delete(name) {
if (!this.#validate(name, "")) {
return;
}
if (this.guard === "request-no-cors" &&
!isNoCORSSafelistedRequestHeaderName(name) &&
!isPrivilegedNoCORSRequestHeaderName(name)) {
return;
}
if (!this.headerList.contains(name)) {
return;
}
this.headerList.delete(name);
if (this.guard === "request-no-cors") {
this.#removePrivilegedNoCORSHeaders();
}
}
// https://fetch.spec.whatwg.org/#dom-headers-get
get(name) {
assertName(name);
return this.headerList.get(name);
}
// https://fetch.spec.whatwg.org/#dom-headers-getsetcookie
getSetCookie() {
return this.headerList.getAll("Set-Cookie") || [];
}
// https://fetch.spec.whatwg.org/#dom-headers-has
has(name) {
assertName(name);
return this.headerList.contains(name);
}
// https://fetch.spec.whatwg.org/#dom-headers-set
set(name, value) {
value = normalizeHeaderValue(value);
if (!this.#validate(name, value)) {
return;
}
if (this.guard === "request-no-cors" && !isNoCORSSafelistedRequestHeader(name, value)) {
return;
}
this.headerList.set(name, value);
if (this.guard === "request-no-cors") {
this.#removePrivilegedNoCORSHeaders();
}
}
* [Symbol.iterator]() {
for (const header of this.headerList.sortAndCombine()) {
yield header;
}
}
}
exports.implementation = HeadersImpl;

View File

@@ -0,0 +1,158 @@
"use strict";
/**
* Provides utility functions for efficiently managing a collection of headers. Corresponds to
* https://fetch.spec.whatwg.org/#concept-header-list.
*
* Notably, unlike `Headers`, this allows retrieving the original casing of header names and does no normalization of
* inputs, which is important for implementing `XMLHttpRequest`. See discussions on, e.g.,
* https://github.com/whatwg/fetch/pull/476.
*
*/
class HeaderList {
// Note: we can use normal `toLowerCase()` in this class, instead of `asciiLowercase()`, because we assume all inputs
// are byte strings.
constructor() {
// Internal storage: Map<lowercaseName, {name: originalName, values: Array<value>}>
this._headers = new Map();
}
// https://fetch.spec.whatwg.org/#concept-header-list-append
append(name, value) {
const lower = name.toLowerCase();
const existing = this._headers.get(lower);
if (existing) {
existing.values.push(value);
} else {
this._headers.set(lower, { name, values: [value] });
}
}
// https://fetch.spec.whatwg.org/#header-list-contains
contains(name) {
return this._headers.has(name.toLowerCase());
}
// https://fetch.spec.whatwg.org/#concept-header-list-get
get(name) {
const entry = this._headers.get(name.toLowerCase());
if (!entry) {
return null;
}
return entry.values.join(", ");
}
// No corresponding spec algorithm, but equivalent to e.g. the steps used in
// https://fetch.spec.whatwg.org/#dom-headers-getsetcookie.
getAll(name) {
const entry = this._headers.get(name.toLowerCase());
if (!entry) {
return null;
}
return entry.values;
}
// https://fetch.spec.whatwg.org/#concept-header-list-delete
delete(name) {
this._headers.delete(name.toLowerCase());
}
// https://fetch.spec.whatwg.org/#concept-header-list-set
set(name, value) {
const lower = name.toLowerCase();
this._headers.set(lower, { name, values: [value] });
}
// https://fetch.spec.whatwg.org/#concept-header-list-combine
combine(name, value) {
const lower = name.toLowerCase();
const existing = this._headers.get(lower);
if (existing) {
existing.values[0] += ", " + value;
} else {
this._headers.set(lower, { name, values: [value] });
}
}
// https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine
sortAndCombine() {
const names = [...this._headers.keys()].sort();
const headers = [];
for (const name of names) {
const { values } = this._headers.get(name);
if (name === "set-cookie") {
for (const value of values) {
headers.push([name, value]);
}
} else {
headers.push([name, values.join(", ")]);
}
}
return headers;
}
/**
* Yields [name, value] pairs for iteration.
* Each header with multiple values yields multiple pairs.
* Preserves original casing.
*/
* [Symbol.iterator]() {
for (const { name, values } of this._headers.values()) {
for (const value of values) {
yield [name, value];
}
}
}
/**
* Yields unique header names (with original casing).
*/
* names() {
for (const { name } of this._headers.values()) {
yield name;
}
}
/**
* Serializes the header list to an object.
* Format matches undici's headers object: {name: value} or {name: [values]} for multiple values.
*/
toJSON() {
const result = {};
for (const { name, values } of this._headers.values()) {
result[name] = values.length === 1 ? values[0] : values;
}
return result;
}
/**
* Creates a HeaderList from a headers object.
* Format: {name: value} or {name: [values]} for multiple values.
* @param {object} obj - Headers object
*/
static fromJSON(obj) {
const list = new HeaderList();
for (const [name, value] of Object.entries(obj)) {
if (Array.isArray(value)) {
for (const v of value) {
list.append(name, v);
}
} else {
list.append(name, value);
}
}
return list;
}
/**
* Creates a copy of this HeaderList.
*/
clone() {
return HeaderList.fromJSON(this.toJSON());
}
}
module.exports = HeaderList;

View File

@@ -0,0 +1,205 @@
"use strict";
const { MIMEType } = require("whatwg-mimetype");
// https://fetch.spec.whatwg.org/#privileged-no-cors-request-header-name
const PRIVILEGED_NO_CORS_REQUEST = new Set(["range"]);
function isPrivilegedNoCORSRequestHeaderName(name) {
return PRIVILEGED_NO_CORS_REQUEST.has(name.toLowerCase());
}
// https://fetch.spec.whatwg.org/#no-cors-safelisted-request-header-name
const NO_CORS_SAFELISTED_REQUEST = new Set([
`accept`,
`accept-language`,
`content-language`,
`content-type`
]);
function isNoCORSSafelistedRequestHeaderName(name) {
return NO_CORS_SAFELISTED_REQUEST.has(name.toLowerCase());
}
// https://fetch.spec.whatwg.org/#forbidden-response-header-name
const FORBIDDEN_RESPONSE = new Set(["set-cookie", "set-cookie2"]);
function isForbiddenResponseHeaderName(name) {
return FORBIDDEN_RESPONSE.has(name.toLowerCase());
}
// https://fetch.spec.whatwg.org/#cors-safelisted-request-header
// Note: name and value are already ensured by the IDL layer to be byte strings.
const CORS_UNSAFE_BYTE = /[\x00-\x08\x0A-\x1F"():<>?@[\\\]{}\x7F]/;
function isCORSSafelistedRequestHeader(name, value) {
name = name.toLowerCase();
switch (name) {
case "accept":
if (value.match(CORS_UNSAFE_BYTE)) {
return false;
}
break;
case "accept-language":
case "content-language":
if (value.match(/[^\x30-\x39\x41-\x5A\x61-\x7A *,\-.;=]/)) {
return false;
}
break;
case "content-type": {
if (value.match(CORS_UNSAFE_BYTE)) {
return false;
}
const mimeType = MIMEType.parse(value);
if (mimeType === null) {
return false;
}
if (
![
"application/x-www-form-urlencoded",
"multipart/form-data",
"text/plain"
].includes(mimeType.essence)
) {
return false;
}
break;
}
default:
return false;
}
if (value.length > 128) {
return false;
}
return true;
}
// https://fetch.spec.whatwg.org/#no-cors-safelisted-request-header
function isNoCORSSafelistedRequestHeader(name, value) {
if (!isNoCORSSafelistedRequestHeaderName(name)) {
return false;
}
return isCORSSafelistedRequestHeader(name, value);
}
const BASIC_FORBIDDEN_REQUEST_HEADERS = new Set([
"accept-charset",
"accept-encoding",
"access-control-request-headers",
"access-control-request-method",
"connection",
"content-length",
"cookie",
"cookie2",
"date",
"dnt",
"expect",
"host",
"keep-alive",
"origin",
"referer",
"te",
"trailer",
"transfer-encoding",
"upgrade",
"via"
]);
const METHOD_CHECKING_FORBIDDEN_REQUEST_HEADERS = new Set([
"x-http-method",
"x-http-method-override",
"x-method-override"
]);
const FORBIDDEN_METHODS = new Set([
"connect",
"trace",
"track"
]);
// https://fetch.spec.whatwg.org/#forbidden-method
function isForbiddenMethod(value) {
return FORBIDDEN_METHODS.has(value.toLowerCase());
}
// https://fetch.spec.whatwg.org/#forbidden-request-header
function isForbiddenRequestHeader(name, value) {
const lowercaseName = name.toLowerCase();
if (BASIC_FORBIDDEN_REQUEST_HEADERS.has(lowercaseName)) {
return true;
}
if (lowercaseName.startsWith("proxy-") || lowercaseName.startsWith("sec-")) {
return true;
}
if (METHOD_CHECKING_FORBIDDEN_REQUEST_HEADERS.has(lowercaseName)) {
const parsedValues = getDecodeAndSplit(value);
return parsedValues.some(isForbiddenMethod);
}
return false;
}
// https://fetch.spec.whatwg.org/#header-value-get-decode-and-split
function getDecodeAndSplit(input) {
const values = [];
let temporaryValue = "";
let position = 0;
while (true) {
// Collect sequence of code points that are not " or ,
while (position < input.length && input[position] !== "\"" && input[position] !== ",") {
temporaryValue += input[position++];
}
// If position is not past end and code point is "
if (position < input.length && input[position] === '"') {
// Inlined: collect HTTP quoted string (extract-value = false)
const positionStart = position++;
while (true) {
while (position < input.length && input[position] !== "\"" && input[position] !== "\\") {
position++;
}
if (position >= input.length) {
break;
}
if (input[position++] === "\\") {
if (position >= input.length) {
break;
}
position++;
} else {
break; // It was "
}
}
temporaryValue += input.slice(positionStart, position);
if (position < input.length) {
continue;
}
}
// Remove HTTP tab or space from start and end
let start = 0;
let end = temporaryValue.length;
while (start < end && (temporaryValue[start] === "\t" || temporaryValue[start] === " ")) {
start++;
}
while (end > start && (temporaryValue[end - 1] === "\t" || temporaryValue[end - 1] === " ")) {
end--;
}
values.push(temporaryValue.slice(start, end));
temporaryValue = "";
if (position >= input.length) {
return values;
}
// Assert: code point at position is ,
position++;
}
}
module.exports = {
isPrivilegedNoCORSRequestHeaderName,
isNoCORSSafelistedRequestHeaderName,
isNoCORSSafelistedRequestHeader,
isForbiddenRequestHeader,
isForbiddenResponseHeaderName,
isCORSSafelistedRequestHeader
};

View File

@@ -0,0 +1,26 @@
"use strict";
// https://fetch.spec.whatwg.org/#header-name
function isHeaderName(name) {
return /^[!#$%&'*+\-.^`|~\w]+$/.test(name);
}
// https://fetch.spec.whatwg.org/#header-value
function isHeaderValue(value) {
return value[0] !== "\t" &&
value[0] !== " " &&
value[value.length - 1] !== "\t" &&
value[value.length - 1] !== " " &&
!/[\0\r\n]/.test(value);
}
// https://fetch.spec.whatwg.org/#concept-header-value-normalize
function normalizeHeaderValue(potentialValue) {
return potentialValue.replace(/^[\n\r\t ]+|[\n\r\t ]+$/g, "");
}
module.exports = {
isHeaderName,
isHeaderValue,
normalizeHeaderValue
};

View File

@@ -0,0 +1,111 @@
"use strict";
const { utf8Encode } = require("../helpers/encoding");
const Blob = require("../generated/Blob");
const { isArrayBuffer } = require("../generated/utils");
const { concatTypedArrays } = require("../helpers/binary-data");
function convertLineEndingsToNative(s) {
// jsdom always pretends to be *nix, for consistency.
// See also https://github.com/jsdom/jsdom/issues/2396.
return s.replace(/\r\n|\r|\n/g, "\n");
}
exports.implementation = class BlobImpl {
constructor(globalObject, [parts, properties], { fastPathArrayBufferToWrap } = {}) {
this._globalObject = globalObject;
this.type = properties.type;
if (/[^\u0020-\u007E]/.test(this.type)) {
this.type = "";
} else {
this.type = this.type.toLowerCase();
}
// A word about `this._bytes`:
//
// It is a `Uint8Array`. The realm of that `Uint8Array`, and/or the realm of its underlying `ArrayBuffer`, may be
// arbitrary. In particular, they likely do *not* match `this._globalObject`. The underlying `ArrayBuffer` may have
// been acquired from some other part of the system, e.g., the `ws` library, or aliased to another `BlobImpl`'s
// `_bytes`.
//
// This is fine, and indeed desirable, for efficiency. The key is that `Blob` is conceptually immutable, so users
// will never mutate the underlying `ArrayBuffer`. And, we never expose `this._bytes` or the underlying
// `ArrayBuffer` directly to the user: we always use something like `copyToArrayBufferInTargetRealm()` to ensure the
// result is in the realm appropriate for the user's request, and that if the user mutates the exposed bytes, this
// doesn't impact `this._bytes`.
// Used internally in jsdom when we receive an `ArrayBuffer` from elsewhere in the system and know we don't need to
// copy it because the user doesn't have any references to it. It's OK if `fastPathArrayBufferToWrap` is in the
// wrong realm even, because it never directly escapes the `BlobImpl` without a copy.
if (fastPathArrayBufferToWrap) {
this._bytes = new Uint8Array(fastPathArrayBufferToWrap);
return;
}
const chunks = [];
if (parts !== undefined) {
for (const part of parts) {
let chunk;
if (isArrayBuffer(part)) {
// Create a wrapper. The copying will happen in `concatTypedArrays()`.
chunk = new Uint8Array(part);
} else if (ArrayBuffer.isView(part)) {
// Use the part as-is. The copying will happen in `concatTypedArrays()`.
chunk = part;
} else if (Blob.isImpl(part)) {
// Use the existing `Uint8Array` as-is. The copying will happen in `concatTypedArrays()`.
chunk = part._bytes;
} else {
let s = part;
if (properties.endings === "native") {
s = convertLineEndingsToNative(s);
}
chunk = utf8Encode(s);
}
chunks.push(chunk);
}
}
this._bytes = concatTypedArrays(chunks);
}
get size() {
return this._bytes.length;
}
slice(start, end, contentType) {
const { size } = this;
let relativeStart, relativeEnd, relativeContentType;
if (start === undefined) {
relativeStart = 0;
} else if (start < 0) {
relativeStart = Math.max(size + start, 0);
} else {
relativeStart = Math.min(start, size);
}
if (end === undefined) {
relativeEnd = size;
} else if (end < 0) {
relativeEnd = Math.max(size + end, 0);
} else {
relativeEnd = Math.min(end, size);
}
if (contentType === undefined) {
relativeContentType = "";
} else {
// sanitization (lower case and invalid char check) is done in the
// constructor
relativeContentType = contentType;
}
const span = Math.max(relativeEnd - relativeStart, 0);
const slicedBuffer = this._bytes.slice(relativeStart, relativeStart + span);
const blob = Blob.createImpl(this._globalObject, [[], { type: relativeContentType }], {});
blob._bytes = slicedBuffer;
return blob;
}
};

View File

@@ -0,0 +1,12 @@
"use strict";
const BlobImpl = require("./Blob-impl").implementation;
exports.implementation = class FileImpl extends BlobImpl {
constructor(globalObject, [fileBits, fileName, options], privateData) {
super(globalObject, [fileBits, options], privateData);
this.name = fileName;
this.lastModified = "lastModified" in options ? options.lastModified : Date.now();
}
};

View File

@@ -0,0 +1,15 @@
"use strict";
const idlUtils = require("../generated/utils.js");
exports.implementation = class FileListImpl extends Array {
constructor() {
super(0);
}
item(index) {
return this[index] || null;
}
get [idlUtils.supportedPropertyIndices]() {
return this.keys();
}
};

View File

@@ -0,0 +1,132 @@
"use strict";
const { labelToName, legacyHookDecode } = require("@exodus/bytes/encoding.js");
const { toBase64 } = require("@exodus/bytes/base64.js");
const { MIMEType } = require("whatwg-mimetype");
const DOMException = require("../generated/DOMException");
const EventTargetImpl = require("../events/EventTarget-impl").implementation;
const ProgressEvent = require("../generated/ProgressEvent");
const { setupForSimpleEventAccessors } = require("../helpers/create-event-accessor");
const { fireAnEvent } = require("../helpers/events");
const { copyToArrayBufferInTargetRealm } = require("../helpers/binary-data");
const READY_STATES = Object.freeze({
EMPTY: 0,
LOADING: 1,
DONE: 2
});
const events = ["loadstart", "progress", "load", "abort", "error", "loadend"];
class FileReaderImpl extends EventTargetImpl {
constructor(globalObject, args, privateData) {
super(globalObject, args, privateData);
this.error = null;
this.readyState = READY_STATES.EMPTY;
this.result = null;
this._globalObject = globalObject;
this._ownerDocument = globalObject.document;
this._terminated = false;
}
readAsArrayBuffer(file) {
this._readFile(file, "buffer");
}
readAsBinaryString(file) {
this._readFile(file, "binaryString");
}
readAsDataURL(file) {
this._readFile(file, "dataURL");
}
readAsText(file, encodingLabel) {
this._readFile(file, "text", labelToName(encodingLabel) || "UTF-8");
}
abort() {
if (this.readyState === READY_STATES.EMPTY || this.readyState === READY_STATES.DONE) {
this.result = null;
return;
}
if (this.readyState === READY_STATES.LOADING) {
this.readyState = READY_STATES.DONE;
this.result = null;
}
this._terminated = true;
this._fireProgressEvent("abort");
this._fireProgressEvent("loadend");
}
_fireProgressEvent(name, props) {
fireAnEvent(name, this, ProgressEvent, props);
}
_readFile(file, format, encodingLabel) {
if (this.readyState === READY_STATES.LOADING) {
throw DOMException.create(this._globalObject, [
"The object is in an invalid state.",
"InvalidStateError"
]);
}
this.readyState = READY_STATES.LOADING;
setImmediate(() => {
if (this._terminated) {
this._terminated = false;
return;
}
this._fireProgressEvent("loadstart");
this._fireProgressEvent("progress", {
lengthComputable: !isNaN(file.size),
total: file.size,
loaded: file._bytes.length
});
setImmediate(() => {
if (this._terminated) {
this._terminated = false;
return;
}
switch (format) {
case "binaryString": {
// Convert Uint8Array to binary string (each byte as a code point)
let binaryString = "";
for (let i = 0; i < file._bytes.length; i++) {
binaryString += String.fromCharCode(file._bytes[i]);
}
this.result = binaryString;
break;
}
case "dataURL": {
// Spec seems very unclear here; see https://github.com/w3c/FileAPI/issues/104.
const contentType = MIMEType.parse(file.type) || "application/octet-stream";
this.result = `data:${contentType};base64,${toBase64(file._bytes)}`;
break;
}
case "text": {
this.result = legacyHookDecode(file._bytes, encodingLabel);
break;
}
case "buffer":
default: {
this.result = copyToArrayBufferInTargetRealm(file._bytes.buffer, this._globalObject);
break;
}
}
this.readyState = READY_STATES.DONE;
this._fireProgressEvent("load");
this._fireProgressEvent("loadend");
});
});
}
}
setupForSimpleEventAccessors(FileReaderImpl.prototype, events);
exports.implementation = FileReaderImpl;

View File

@@ -0,0 +1,143 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const implSymbol = utils.implSymbol;
const ctorRegistrySymbol = utils.ctorRegistrySymbol;
const interfaceName = "AbortController";
exports.is = value => {
return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};
exports.isImpl = value => {
return utils.isObject(value) && value instanceof Impl.implementation;
};
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (exports.is(value)) {
return utils.implForWrapper(value);
}
throw new globalObject.TypeError(`${context} is not of type 'AbortController'.`);
};
function makeWrapper(globalObject, newTarget) {
let proto;
if (newTarget !== undefined) {
proto = newTarget.prototype;
}
if (!utils.isObject(proto)) {
proto = globalObject[ctorRegistrySymbol]["AbortController"].prototype;
}
return Object.create(proto);
}
exports.create = (globalObject, constructorArgs, privateData) => {
const wrapper = makeWrapper(globalObject);
return exports.setup(wrapper, globalObject, constructorArgs, privateData);
};
exports.createImpl = (globalObject, constructorArgs, privateData) => {
const wrapper = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(wrapper);
};
exports._internalSetup = (wrapper, globalObject) => {};
exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
privateData.wrapper = wrapper;
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper;
};
exports.new = (globalObject, newTarget) => {
const wrapper = makeWrapper(globalObject, newTarget);
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: Object.create(Impl.implementation.prototype),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper[implSymbol];
};
const exposed = new Set(["Window", "Worker"]);
exports.install = (globalObject, globalNames) => {
if (!globalNames.some(globalName => exposed.has(globalName))) {
return;
}
const ctorRegistry = utils.initCtorRegistry(globalObject);
class AbortController {
constructor() {
return exports.setup(Object.create(new.target.prototype), globalObject, undefined);
}
abort() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'abort' called on an object that is not a valid instance of AbortController."
);
}
const args = [];
{
let curArg = arguments[0];
if (curArg !== undefined) {
curArg = conversions["any"](curArg, {
context: "Failed to execute 'abort' on 'AbortController': parameter 1",
globals: globalObject
});
}
args.push(curArg);
}
return esValue[implSymbol].abort(...args);
}
get signal() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get signal' called on an object that is not a valid instance of AbortController."
);
}
return utils.getSameObject(this, "signal", () => {
return utils.tryWrapperForImpl(esValue[implSymbol]["signal"]);
});
}
}
Object.defineProperties(AbortController.prototype, {
abort: { enumerable: true },
signal: { enumerable: true },
[Symbol.toStringTag]: { value: "AbortController", configurable: true }
});
ctorRegistry[interfaceName] = AbortController;
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: AbortController
});
};
const Impl = require("../aborting/AbortController-impl.js");

View File

@@ -0,0 +1,249 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const EventHandlerNonNull = require("./EventHandlerNonNull.js");
const implSymbol = utils.implSymbol;
const ctorRegistrySymbol = utils.ctorRegistrySymbol;
const EventTarget = require("./EventTarget.js");
const interfaceName = "AbortSignal";
exports.is = value => {
return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};
exports.isImpl = value => {
return utils.isObject(value) && value instanceof Impl.implementation;
};
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (exports.is(value)) {
return utils.implForWrapper(value);
}
throw new globalObject.TypeError(`${context} is not of type 'AbortSignal'.`);
};
function makeWrapper(globalObject, newTarget) {
let proto;
if (newTarget !== undefined) {
proto = newTarget.prototype;
}
if (!utils.isObject(proto)) {
proto = globalObject[ctorRegistrySymbol]["AbortSignal"].prototype;
}
return Object.create(proto);
}
exports.create = (globalObject, constructorArgs, privateData) => {
const wrapper = makeWrapper(globalObject);
return exports.setup(wrapper, globalObject, constructorArgs, privateData);
};
exports.createImpl = (globalObject, constructorArgs, privateData) => {
const wrapper = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(wrapper);
};
exports._internalSetup = (wrapper, globalObject) => {
EventTarget._internalSetup(wrapper, globalObject);
};
exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
privateData.wrapper = wrapper;
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper;
};
exports.new = (globalObject, newTarget) => {
const wrapper = makeWrapper(globalObject, newTarget);
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: Object.create(Impl.implementation.prototype),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper[implSymbol];
};
const exposed = new Set(["Window", "Worker"]);
exports.install = (globalObject, globalNames) => {
if (!globalNames.some(globalName => exposed.has(globalName))) {
return;
}
const ctorRegistry = utils.initCtorRegistry(globalObject);
class AbortSignal extends globalObject.EventTarget {
constructor() {
throw new globalObject.TypeError("Illegal constructor");
}
throwIfAborted() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'throwIfAborted' called on an object that is not a valid instance of AbortSignal."
);
}
return esValue[implSymbol].throwIfAborted();
}
get aborted() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get aborted' called on an object that is not a valid instance of AbortSignal."
);
}
return esValue[implSymbol]["aborted"];
}
get reason() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get reason' called on an object that is not a valid instance of AbortSignal."
);
}
return esValue[implSymbol]["reason"];
}
get onabort() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get onabort' called on an object that is not a valid instance of AbortSignal."
);
}
return utils.tryWrapperForImpl(esValue[implSymbol]["onabort"]);
}
set onabort(V) {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'set onabort' called on an object that is not a valid instance of AbortSignal."
);
}
if (!utils.isObject(V)) {
V = null;
} else {
V = EventHandlerNonNull.convert(globalObject, V, {
context: "Failed to set the 'onabort' property on 'AbortSignal': The provided value"
});
}
esValue[implSymbol]["onabort"] = V;
}
static abort() {
const args = [];
{
let curArg = arguments[0];
if (curArg !== undefined) {
curArg = conversions["any"](curArg, {
context: "Failed to execute 'abort' on 'AbortSignal': parameter 1",
globals: globalObject
});
}
args.push(curArg);
}
return utils.tryWrapperForImpl(Impl.implementation.abort(globalObject, ...args));
}
static timeout(milliseconds) {
if (arguments.length < 1) {
throw new globalObject.TypeError(
`Failed to execute 'timeout' on 'AbortSignal': 1 argument required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
curArg = conversions["unsigned long long"](curArg, {
context: "Failed to execute 'timeout' on 'AbortSignal': parameter 1",
globals: globalObject,
enforceRange: true
});
args.push(curArg);
}
return utils.tryWrapperForImpl(Impl.implementation.timeout(globalObject, ...args));
}
static any(signals) {
if (arguments.length < 1) {
throw new globalObject.TypeError(
`Failed to execute 'any' on 'AbortSignal': 1 argument required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
if (!utils.isObject(curArg)) {
throw new globalObject.TypeError(
"Failed to execute 'any' on 'AbortSignal': parameter 1" + " is not an iterable object."
);
} else {
const V = [];
const tmp = curArg;
for (let nextItem of tmp) {
nextItem = exports.convert(globalObject, nextItem, {
context: "Failed to execute 'any' on 'AbortSignal': parameter 1" + "'s element"
});
V.push(nextItem);
}
curArg = V;
}
args.push(curArg);
}
return utils.tryWrapperForImpl(Impl.implementation.any(globalObject, ...args));
}
}
Object.defineProperties(AbortSignal.prototype, {
throwIfAborted: { enumerable: true },
aborted: { enumerable: true },
reason: { enumerable: true },
onabort: { enumerable: true },
[Symbol.toStringTag]: { value: "AbortSignal", configurable: true }
});
Object.defineProperties(AbortSignal, {
abort: { enumerable: true },
timeout: { enumerable: true },
any: { enumerable: true }
});
ctorRegistry[interfaceName] = AbortSignal;
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: AbortSignal
});
};
const Impl = require("../aborting/AbortSignal-impl.js");

View File

@@ -0,0 +1,171 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const implSymbol = utils.implSymbol;
const ctorRegistrySymbol = utils.ctorRegistrySymbol;
const interfaceName = "AbstractRange";
exports.is = value => {
return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};
exports.isImpl = value => {
return utils.isObject(value) && value instanceof Impl.implementation;
};
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (exports.is(value)) {
return utils.implForWrapper(value);
}
throw new globalObject.TypeError(`${context} is not of type 'AbstractRange'.`);
};
function makeWrapper(globalObject, newTarget) {
let proto;
if (newTarget !== undefined) {
proto = newTarget.prototype;
}
if (!utils.isObject(proto)) {
proto = globalObject[ctorRegistrySymbol]["AbstractRange"].prototype;
}
return Object.create(proto);
}
exports.create = (globalObject, constructorArgs, privateData) => {
const wrapper = makeWrapper(globalObject);
return exports.setup(wrapper, globalObject, constructorArgs, privateData);
};
exports.createImpl = (globalObject, constructorArgs, privateData) => {
const wrapper = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(wrapper);
};
exports._internalSetup = (wrapper, globalObject) => {};
exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
privateData.wrapper = wrapper;
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper;
};
exports.new = (globalObject, newTarget) => {
const wrapper = makeWrapper(globalObject, newTarget);
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: Object.create(Impl.implementation.prototype),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper[implSymbol];
};
const exposed = new Set(["Window"]);
exports.install = (globalObject, globalNames) => {
if (!globalNames.some(globalName => exposed.has(globalName))) {
return;
}
const ctorRegistry = utils.initCtorRegistry(globalObject);
class AbstractRange {
constructor() {
throw new globalObject.TypeError("Illegal constructor");
}
get startContainer() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get startContainer' called on an object that is not a valid instance of AbstractRange."
);
}
return utils.tryWrapperForImpl(esValue[implSymbol]["startContainer"]);
}
get startOffset() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get startOffset' called on an object that is not a valid instance of AbstractRange."
);
}
return esValue[implSymbol]["startOffset"];
}
get endContainer() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get endContainer' called on an object that is not a valid instance of AbstractRange."
);
}
return utils.tryWrapperForImpl(esValue[implSymbol]["endContainer"]);
}
get endOffset() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get endOffset' called on an object that is not a valid instance of AbstractRange."
);
}
return esValue[implSymbol]["endOffset"];
}
get collapsed() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get collapsed' called on an object that is not a valid instance of AbstractRange."
);
}
return esValue[implSymbol]["collapsed"];
}
}
Object.defineProperties(AbstractRange.prototype, {
startContainer: { enumerable: true },
startOffset: { enumerable: true },
endContainer: { enumerable: true },
endOffset: { enumerable: true },
collapsed: { enumerable: true },
[Symbol.toStringTag]: { value: "AbstractRange", configurable: true }
});
ctorRegistry[interfaceName] = AbstractRange;
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: AbstractRange
});
};
const Impl = require("../range/AbstractRange-impl.js");

View File

@@ -0,0 +1,53 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const AbortSignal = require("./AbortSignal.js");
const EventListenerOptions = require("./EventListenerOptions.js");
exports._convertInherit = (globalObject, obj, ret, { context = "The provided value" } = {}) => {
EventListenerOptions._convertInherit(globalObject, obj, ret, { context });
{
const key = "once";
let value = obj === undefined || obj === null ? undefined : obj[key];
if (value !== undefined) {
value = conversions["boolean"](value, { context: context + " has member 'once' that", globals: globalObject });
ret[key] = value;
} else {
ret[key] = false;
}
}
{
const key = "passive";
let value = obj === undefined || obj === null ? undefined : obj[key];
if (value !== undefined) {
value = conversions["boolean"](value, { context: context + " has member 'passive' that", globals: globalObject });
ret[key] = value;
}
}
{
const key = "signal";
let value = obj === undefined || obj === null ? undefined : obj[key];
if (value !== undefined) {
value = AbortSignal.convert(globalObject, value, { context: context + " has member 'signal' that" });
ret[key] = value;
}
}
};
exports.convert = (globalObject, obj, { context = "The provided value" } = {}) => {
if (obj !== undefined && typeof obj !== "object" && typeof obj !== "function") {
throw new globalObject.TypeError(`${context} is not an object.`);
}
const ret = Object.create(null);
exports._convertInherit(globalObject, obj, ret, { context });
return ret;
};

View File

@@ -0,0 +1,28 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
exports._convertInherit = (globalObject, obj, ret, { context = "The provided value" } = {}) => {
{
const key = "flatten";
let value = obj === undefined || obj === null ? undefined : obj[key];
if (value !== undefined) {
value = conversions["boolean"](value, { context: context + " has member 'flatten' that", globals: globalObject });
ret[key] = value;
} else {
ret[key] = false;
}
}
};
exports.convert = (globalObject, obj, { context = "The provided value" } = {}) => {
if (obj !== undefined && typeof obj !== "object" && typeof obj !== "function") {
throw new globalObject.TypeError(`${context} is not an object.`);
}
const ret = Object.create(null);
exports._convertInherit(globalObject, obj, ret, { context });
return ret;
};

217
node_modules/jsdom/lib/jsdom/living/generated/Attr.js generated vendored Normal file
View File

@@ -0,0 +1,217 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const ceReactionsPreSteps_helpers_custom_elements = require("../helpers/custom-elements.js").ceReactionsPreSteps;
const ceReactionsPostSteps_helpers_custom_elements = require("../helpers/custom-elements.js").ceReactionsPostSteps;
const implSymbol = utils.implSymbol;
const ctorRegistrySymbol = utils.ctorRegistrySymbol;
const Node = require("./Node.js");
const interfaceName = "Attr";
exports.is = value => {
return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};
exports.isImpl = value => {
return utils.isObject(value) && value instanceof Impl.implementation;
};
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (exports.is(value)) {
return utils.implForWrapper(value);
}
throw new globalObject.TypeError(`${context} is not of type 'Attr'.`);
};
function makeWrapper(globalObject, newTarget) {
let proto;
if (newTarget !== undefined) {
proto = newTarget.prototype;
}
if (!utils.isObject(proto)) {
proto = globalObject[ctorRegistrySymbol]["Attr"].prototype;
}
return Object.create(proto);
}
exports.create = (globalObject, constructorArgs, privateData) => {
const wrapper = makeWrapper(globalObject);
return exports.setup(wrapper, globalObject, constructorArgs, privateData);
};
exports.createImpl = (globalObject, constructorArgs, privateData) => {
const wrapper = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(wrapper);
};
exports._internalSetup = (wrapper, globalObject) => {
Node._internalSetup(wrapper, globalObject);
};
exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
privateData.wrapper = wrapper;
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper;
};
exports.new = (globalObject, newTarget) => {
const wrapper = makeWrapper(globalObject, newTarget);
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: Object.create(Impl.implementation.prototype),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper[implSymbol];
};
const exposed = new Set(["Window"]);
exports.install = (globalObject, globalNames) => {
if (!globalNames.some(globalName => exposed.has(globalName))) {
return;
}
const ctorRegistry = utils.initCtorRegistry(globalObject);
class Attr extends globalObject.Node {
constructor() {
throw new globalObject.TypeError("Illegal constructor");
}
get namespaceURI() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get namespaceURI' called on an object that is not a valid instance of Attr."
);
}
return esValue[implSymbol]["namespaceURI"];
}
get prefix() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'get prefix' called on an object that is not a valid instance of Attr.");
}
return esValue[implSymbol]["prefix"];
}
get localName() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'get localName' called on an object that is not a valid instance of Attr.");
}
return esValue[implSymbol]["localName"];
}
get name() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'get name' called on an object that is not a valid instance of Attr.");
}
return esValue[implSymbol]["name"];
}
get value() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'get value' called on an object that is not a valid instance of Attr.");
}
ceReactionsPreSteps_helpers_custom_elements(globalObject);
try {
return esValue[implSymbol]["value"];
} finally {
ceReactionsPostSteps_helpers_custom_elements(globalObject);
}
}
set value(V) {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'set value' called on an object that is not a valid instance of Attr.");
}
V = conversions["DOMString"](V, {
context: "Failed to set the 'value' property on 'Attr': The provided value",
globals: globalObject
});
ceReactionsPreSteps_helpers_custom_elements(globalObject);
try {
esValue[implSymbol]["value"] = V;
} finally {
ceReactionsPostSteps_helpers_custom_elements(globalObject);
}
}
get ownerElement() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get ownerElement' called on an object that is not a valid instance of Attr."
);
}
return utils.tryWrapperForImpl(esValue[implSymbol]["ownerElement"]);
}
get specified() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'get specified' called on an object that is not a valid instance of Attr.");
}
return esValue[implSymbol]["specified"];
}
}
Object.defineProperties(Attr.prototype, {
namespaceURI: { enumerable: true },
prefix: { enumerable: true },
localName: { enumerable: true },
name: { enumerable: true },
value: { enumerable: true },
ownerElement: { enumerable: true },
specified: { enumerable: true },
[Symbol.toStringTag]: { value: "Attr", configurable: true }
});
ctorRegistry[interfaceName] = Attr;
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: Attr
});
};
const Impl = require("../attributes/Attr-impl.js");

View File

@@ -0,0 +1,117 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const implSymbol = utils.implSymbol;
const ctorRegistrySymbol = utils.ctorRegistrySymbol;
const interfaceName = "BarProp";
exports.is = value => {
return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};
exports.isImpl = value => {
return utils.isObject(value) && value instanceof Impl.implementation;
};
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (exports.is(value)) {
return utils.implForWrapper(value);
}
throw new globalObject.TypeError(`${context} is not of type 'BarProp'.`);
};
function makeWrapper(globalObject, newTarget) {
let proto;
if (newTarget !== undefined) {
proto = newTarget.prototype;
}
if (!utils.isObject(proto)) {
proto = globalObject[ctorRegistrySymbol]["BarProp"].prototype;
}
return Object.create(proto);
}
exports.create = (globalObject, constructorArgs, privateData) => {
const wrapper = makeWrapper(globalObject);
return exports.setup(wrapper, globalObject, constructorArgs, privateData);
};
exports.createImpl = (globalObject, constructorArgs, privateData) => {
const wrapper = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(wrapper);
};
exports._internalSetup = (wrapper, globalObject) => {};
exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
privateData.wrapper = wrapper;
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper;
};
exports.new = (globalObject, newTarget) => {
const wrapper = makeWrapper(globalObject, newTarget);
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: Object.create(Impl.implementation.prototype),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper[implSymbol];
};
const exposed = new Set(["Window"]);
exports.install = (globalObject, globalNames) => {
if (!globalNames.some(globalName => exposed.has(globalName))) {
return;
}
const ctorRegistry = utils.initCtorRegistry(globalObject);
class BarProp {
constructor() {
throw new globalObject.TypeError("Illegal constructor");
}
get visible() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'get visible' called on an object that is not a valid instance of BarProp.");
}
return esValue[implSymbol]["visible"];
}
}
Object.defineProperties(BarProp.prototype, {
visible: { enumerable: true },
[Symbol.toStringTag]: { value: "BarProp", configurable: true }
});
ctorRegistry[interfaceName] = BarProp;
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: BarProp
});
};
const Impl = require("../window/BarProp-impl.js");

View File

@@ -0,0 +1,139 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const implSymbol = utils.implSymbol;
const ctorRegistrySymbol = utils.ctorRegistrySymbol;
const Event = require("./Event.js");
const interfaceName = "BeforeUnloadEvent";
exports.is = value => {
return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};
exports.isImpl = value => {
return utils.isObject(value) && value instanceof Impl.implementation;
};
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (exports.is(value)) {
return utils.implForWrapper(value);
}
throw new globalObject.TypeError(`${context} is not of type 'BeforeUnloadEvent'.`);
};
function makeWrapper(globalObject, newTarget) {
let proto;
if (newTarget !== undefined) {
proto = newTarget.prototype;
}
if (!utils.isObject(proto)) {
proto = globalObject[ctorRegistrySymbol]["BeforeUnloadEvent"].prototype;
}
return Object.create(proto);
}
exports.create = (globalObject, constructorArgs, privateData) => {
const wrapper = makeWrapper(globalObject);
return exports.setup(wrapper, globalObject, constructorArgs, privateData);
};
exports.createImpl = (globalObject, constructorArgs, privateData) => {
const wrapper = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(wrapper);
};
exports._internalSetup = (wrapper, globalObject) => {
Event._internalSetup(wrapper, globalObject);
};
exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
privateData.wrapper = wrapper;
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper;
};
exports.new = (globalObject, newTarget) => {
const wrapper = makeWrapper(globalObject, newTarget);
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: Object.create(Impl.implementation.prototype),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper[implSymbol];
};
const exposed = new Set(["Window"]);
exports.install = (globalObject, globalNames) => {
if (!globalNames.some(globalName => exposed.has(globalName))) {
return;
}
const ctorRegistry = utils.initCtorRegistry(globalObject);
class BeforeUnloadEvent extends globalObject.Event {
constructor() {
throw new globalObject.TypeError("Illegal constructor");
}
get returnValue() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get returnValue' called on an object that is not a valid instance of BeforeUnloadEvent."
);
}
return esValue[implSymbol]["returnValue"];
}
set returnValue(V) {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'set returnValue' called on an object that is not a valid instance of BeforeUnloadEvent."
);
}
V = conversions["DOMString"](V, {
context: "Failed to set the 'returnValue' property on 'BeforeUnloadEvent': The provided value",
globals: globalObject
});
esValue[implSymbol]["returnValue"] = V;
}
}
Object.defineProperties(BeforeUnloadEvent.prototype, {
returnValue: { enumerable: true },
[Symbol.toStringTag]: { value: "BeforeUnloadEvent", configurable: true }
});
ctorRegistry[interfaceName] = BeforeUnloadEvent;
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: BeforeUnloadEvent
});
};
const Impl = require("../events/BeforeUnloadEvent-impl.js");

View File

@@ -0,0 +1,12 @@
"use strict";
const enumerationValues = new Set(["blob", "arraybuffer"]);
exports.enumerationValues = enumerationValues;
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
const string = `${value}`;
if (!enumerationValues.has(string)) {
throw new globalObject.TypeError(`${context} '${string}' is not a valid enumeration value for BinaryType`);
}
return string;
};

211
node_modules/jsdom/lib/jsdom/living/generated/Blob.js generated vendored Normal file
View File

@@ -0,0 +1,211 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const BlobPropertyBag = require("./BlobPropertyBag.js");
const implSymbol = utils.implSymbol;
const ctorRegistrySymbol = utils.ctorRegistrySymbol;
const interfaceName = "Blob";
exports.is = value => {
return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};
exports.isImpl = value => {
return utils.isObject(value) && value instanceof Impl.implementation;
};
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (exports.is(value)) {
return utils.implForWrapper(value);
}
throw new globalObject.TypeError(`${context} is not of type 'Blob'.`);
};
function makeWrapper(globalObject, newTarget) {
let proto;
if (newTarget !== undefined) {
proto = newTarget.prototype;
}
if (!utils.isObject(proto)) {
proto = globalObject[ctorRegistrySymbol]["Blob"].prototype;
}
return Object.create(proto);
}
exports.create = (globalObject, constructorArgs, privateData) => {
const wrapper = makeWrapper(globalObject);
return exports.setup(wrapper, globalObject, constructorArgs, privateData);
};
exports.createImpl = (globalObject, constructorArgs, privateData) => {
const wrapper = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(wrapper);
};
exports._internalSetup = (wrapper, globalObject) => {};
exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
privateData.wrapper = wrapper;
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper;
};
exports.new = (globalObject, newTarget) => {
const wrapper = makeWrapper(globalObject, newTarget);
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: Object.create(Impl.implementation.prototype),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper[implSymbol];
};
const exposed = new Set(["Window", "Worker"]);
exports.install = (globalObject, globalNames) => {
if (!globalNames.some(globalName => exposed.has(globalName))) {
return;
}
const ctorRegistry = utils.initCtorRegistry(globalObject);
class Blob {
constructor() {
const args = [];
{
let curArg = arguments[0];
if (curArg !== undefined) {
if (!utils.isObject(curArg)) {
throw new globalObject.TypeError("Failed to construct 'Blob': parameter 1" + " is not an iterable object.");
} else {
const V = [];
const tmp = curArg;
for (let nextItem of tmp) {
if (exports.is(nextItem)) {
nextItem = utils.implForWrapper(nextItem);
} else if (utils.isArrayBuffer(nextItem)) {
nextItem = conversions["ArrayBuffer"](nextItem, {
context: "Failed to construct 'Blob': parameter 1" + "'s element",
globals: globalObject
});
} else if (ArrayBuffer.isView(nextItem)) {
nextItem = conversions["ArrayBufferView"](nextItem, {
context: "Failed to construct 'Blob': parameter 1" + "'s element",
globals: globalObject
});
} else {
nextItem = conversions["USVString"](nextItem, {
context: "Failed to construct 'Blob': parameter 1" + "'s element",
globals: globalObject
});
}
V.push(nextItem);
}
curArg = V;
}
}
args.push(curArg);
}
{
let curArg = arguments[1];
curArg = BlobPropertyBag.convert(globalObject, curArg, { context: "Failed to construct 'Blob': parameter 2" });
args.push(curArg);
}
return exports.setup(Object.create(new.target.prototype), globalObject, args);
}
slice() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'slice' called on an object that is not a valid instance of Blob.");
}
const args = [];
{
let curArg = arguments[0];
if (curArg !== undefined) {
curArg = conversions["long long"](curArg, {
context: "Failed to execute 'slice' on 'Blob': parameter 1",
globals: globalObject,
clamp: true
});
}
args.push(curArg);
}
{
let curArg = arguments[1];
if (curArg !== undefined) {
curArg = conversions["long long"](curArg, {
context: "Failed to execute 'slice' on 'Blob': parameter 2",
globals: globalObject,
clamp: true
});
}
args.push(curArg);
}
{
let curArg = arguments[2];
if (curArg !== undefined) {
curArg = conversions["DOMString"](curArg, {
context: "Failed to execute 'slice' on 'Blob': parameter 3",
globals: globalObject
});
}
args.push(curArg);
}
return utils.tryWrapperForImpl(esValue[implSymbol].slice(...args));
}
get size() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'get size' called on an object that is not a valid instance of Blob.");
}
return esValue[implSymbol]["size"];
}
get type() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'get type' called on an object that is not a valid instance of Blob.");
}
return esValue[implSymbol]["type"];
}
}
Object.defineProperties(Blob.prototype, {
slice: { enumerable: true },
size: { enumerable: true },
type: { enumerable: true },
[Symbol.toStringTag]: { value: "Blob", configurable: true }
});
ctorRegistry[interfaceName] = Blob;
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: Blob
});
};
const Impl = require("../file-api/Blob-impl.js");

View File

@@ -0,0 +1,30 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (typeof value !== "function") {
throw new globalObject.TypeError(context + " is not a function");
}
function invokeTheCallbackFunction(blob) {
const thisArg = utils.tryWrapperForImpl(this);
let callResult;
blob = utils.tryWrapperForImpl(blob);
callResult = Reflect.apply(value, thisArg, [blob]);
}
invokeTheCallbackFunction.construct = blob => {
blob = utils.tryWrapperForImpl(blob);
let callResult = Reflect.construct(value, [blob]);
};
invokeTheCallbackFunction[utils.wrapperSymbol] = value;
invokeTheCallbackFunction.objectReference = value;
return invokeTheCallbackFunction;
};

View File

@@ -0,0 +1,157 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const BlobEventInit = require("./BlobEventInit.js");
const implSymbol = utils.implSymbol;
const ctorRegistrySymbol = utils.ctorRegistrySymbol;
const Event = require("./Event.js");
const interfaceName = "BlobEvent";
exports.is = value => {
return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};
exports.isImpl = value => {
return utils.isObject(value) && value instanceof Impl.implementation;
};
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (exports.is(value)) {
return utils.implForWrapper(value);
}
throw new globalObject.TypeError(`${context} is not of type 'BlobEvent'.`);
};
function makeWrapper(globalObject, newTarget) {
let proto;
if (newTarget !== undefined) {
proto = newTarget.prototype;
}
if (!utils.isObject(proto)) {
proto = globalObject[ctorRegistrySymbol]["BlobEvent"].prototype;
}
return Object.create(proto);
}
exports.create = (globalObject, constructorArgs, privateData) => {
const wrapper = makeWrapper(globalObject);
return exports.setup(wrapper, globalObject, constructorArgs, privateData);
};
exports.createImpl = (globalObject, constructorArgs, privateData) => {
const wrapper = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(wrapper);
};
exports._internalSetup = (wrapper, globalObject) => {
Event._internalSetup(wrapper, globalObject);
};
exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
privateData.wrapper = wrapper;
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper;
};
exports.new = (globalObject, newTarget) => {
const wrapper = makeWrapper(globalObject, newTarget);
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: Object.create(Impl.implementation.prototype),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper[implSymbol];
};
const exposed = new Set(["Window"]);
exports.install = (globalObject, globalNames) => {
if (!globalNames.some(globalName => exposed.has(globalName))) {
return;
}
const ctorRegistry = utils.initCtorRegistry(globalObject);
class BlobEvent extends globalObject.Event {
constructor(type, eventInitDict) {
if (arguments.length < 2) {
throw new globalObject.TypeError(
`Failed to construct 'BlobEvent': 2 arguments required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
curArg = conversions["DOMString"](curArg, {
context: "Failed to construct 'BlobEvent': parameter 1",
globals: globalObject
});
args.push(curArg);
}
{
let curArg = arguments[1];
curArg = BlobEventInit.convert(globalObject, curArg, {
context: "Failed to construct 'BlobEvent': parameter 2"
});
args.push(curArg);
}
return exports.setup(Object.create(new.target.prototype), globalObject, args);
}
get data() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'get data' called on an object that is not a valid instance of BlobEvent.");
}
return utils.getSameObject(this, "data", () => {
return utils.tryWrapperForImpl(esValue[implSymbol]["data"]);
});
}
get timecode() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get timecode' called on an object that is not a valid instance of BlobEvent."
);
}
return utils.tryWrapperForImpl(esValue[implSymbol]["timecode"]);
}
}
Object.defineProperties(BlobEvent.prototype, {
data: { enumerable: true },
timecode: { enumerable: true },
[Symbol.toStringTag]: { value: "BlobEvent", configurable: true }
});
ctorRegistry[interfaceName] = BlobEvent;
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: BlobEvent
});
};
const Impl = require("../events/BlobEvent-impl.js");

View File

@@ -0,0 +1,43 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const Blob = require("./Blob.js");
const EventInit = require("./EventInit.js");
exports._convertInherit = (globalObject, obj, ret, { context = "The provided value" } = {}) => {
EventInit._convertInherit(globalObject, obj, ret, { context });
{
const key = "data";
let value = obj === undefined || obj === null ? undefined : obj[key];
if (value !== undefined) {
value = Blob.convert(globalObject, value, { context: context + " has member 'data' that" });
ret[key] = value;
} else {
throw new globalObject.TypeError("data is required in 'BlobEventInit'");
}
}
{
const key = "timecode";
let value = obj === undefined || obj === null ? undefined : obj[key];
if (value !== undefined) {
value = conversions["double"](value, { context: context + " has member 'timecode' that", globals: globalObject });
ret[key] = value;
}
}
};
exports.convert = (globalObject, obj, { context = "The provided value" } = {}) => {
if (obj !== undefined && typeof obj !== "object" && typeof obj !== "function") {
throw new globalObject.TypeError(`${context} is not an object.`);
}
const ret = Object.create(null);
exports._convertInherit(globalObject, obj, ret, { context });
return ret;
};

View File

@@ -0,0 +1,42 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const EndingType = require("./EndingType.js");
exports._convertInherit = (globalObject, obj, ret, { context = "The provided value" } = {}) => {
{
const key = "endings";
let value = obj === undefined || obj === null ? undefined : obj[key];
if (value !== undefined) {
value = EndingType.convert(globalObject, value, { context: context + " has member 'endings' that" });
ret[key] = value;
} else {
ret[key] = "transparent";
}
}
{
const key = "type";
let value = obj === undefined || obj === null ? undefined : obj[key];
if (value !== undefined) {
value = conversions["DOMString"](value, { context: context + " has member 'type' that", globals: globalObject });
ret[key] = value;
} else {
ret[key] = "";
}
}
};
exports.convert = (globalObject, obj, { context = "The provided value" } = {}) => {
if (obj !== undefined && typeof obj !== "object" && typeof obj !== "function") {
throw new globalObject.TypeError(`${context} is not an object.`);
}
const ret = Object.create(null);
exports._convertInherit(globalObject, obj, ret, { context });
return ret;
};

View File

@@ -0,0 +1,109 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const implSymbol = utils.implSymbol;
const ctorRegistrySymbol = utils.ctorRegistrySymbol;
const Text = require("./Text.js");
const interfaceName = "CDATASection";
exports.is = value => {
return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};
exports.isImpl = value => {
return utils.isObject(value) && value instanceof Impl.implementation;
};
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (exports.is(value)) {
return utils.implForWrapper(value);
}
throw new globalObject.TypeError(`${context} is not of type 'CDATASection'.`);
};
function makeWrapper(globalObject, newTarget) {
let proto;
if (newTarget !== undefined) {
proto = newTarget.prototype;
}
if (!utils.isObject(proto)) {
proto = globalObject[ctorRegistrySymbol]["CDATASection"].prototype;
}
return Object.create(proto);
}
exports.create = (globalObject, constructorArgs, privateData) => {
const wrapper = makeWrapper(globalObject);
return exports.setup(wrapper, globalObject, constructorArgs, privateData);
};
exports.createImpl = (globalObject, constructorArgs, privateData) => {
const wrapper = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(wrapper);
};
exports._internalSetup = (wrapper, globalObject) => {
Text._internalSetup(wrapper, globalObject);
};
exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
privateData.wrapper = wrapper;
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper;
};
exports.new = (globalObject, newTarget) => {
const wrapper = makeWrapper(globalObject, newTarget);
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: Object.create(Impl.implementation.prototype),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper[implSymbol];
};
const exposed = new Set(["Window"]);
exports.install = (globalObject, globalNames) => {
if (!globalNames.some(globalName => exposed.has(globalName))) {
return;
}
const ctorRegistry = utils.initCtorRegistry(globalObject);
class CDATASection extends globalObject.Text {
constructor() {
throw new globalObject.TypeError("Illegal constructor");
}
}
Object.defineProperties(CDATASection.prototype, {
[Symbol.toStringTag]: { value: "CDATASection", configurable: true }
});
ctorRegistry[interfaceName] = CDATASection;
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: CDATASection
});
};
const Impl = require("../nodes/CDATASection-impl.js");

View File

@@ -0,0 +1,12 @@
"use strict";
const enumerationValues = new Set(["", "maybe", "probably"]);
exports.enumerationValues = enumerationValues;
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
const string = `${value}`;
if (!enumerationValues.has(string)) {
throw new globalObject.TypeError(`${context} '${string}' is not a valid enumeration value for CanPlayTypeResult`);
}
return string;
};

View File

@@ -0,0 +1,453 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const Node = require("./Node.js");
const ceReactionsPreSteps_helpers_custom_elements = require("../helpers/custom-elements.js").ceReactionsPreSteps;
const ceReactionsPostSteps_helpers_custom_elements = require("../helpers/custom-elements.js").ceReactionsPostSteps;
const implSymbol = utils.implSymbol;
const ctorRegistrySymbol = utils.ctorRegistrySymbol;
const interfaceName = "CharacterData";
exports.is = value => {
return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};
exports.isImpl = value => {
return utils.isObject(value) && value instanceof Impl.implementation;
};
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (exports.is(value)) {
return utils.implForWrapper(value);
}
throw new globalObject.TypeError(`${context} is not of type 'CharacterData'.`);
};
function makeWrapper(globalObject, newTarget) {
let proto;
if (newTarget !== undefined) {
proto = newTarget.prototype;
}
if (!utils.isObject(proto)) {
proto = globalObject[ctorRegistrySymbol]["CharacterData"].prototype;
}
return Object.create(proto);
}
exports.create = (globalObject, constructorArgs, privateData) => {
const wrapper = makeWrapper(globalObject);
return exports.setup(wrapper, globalObject, constructorArgs, privateData);
};
exports.createImpl = (globalObject, constructorArgs, privateData) => {
const wrapper = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(wrapper);
};
exports._internalSetup = (wrapper, globalObject) => {
Node._internalSetup(wrapper, globalObject);
};
exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
privateData.wrapper = wrapper;
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper;
};
exports.new = (globalObject, newTarget) => {
const wrapper = makeWrapper(globalObject, newTarget);
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: Object.create(Impl.implementation.prototype),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper[implSymbol];
};
const exposed = new Set(["Window"]);
exports.install = (globalObject, globalNames) => {
if (!globalNames.some(globalName => exposed.has(globalName))) {
return;
}
const ctorRegistry = utils.initCtorRegistry(globalObject);
class CharacterData extends globalObject.Node {
constructor() {
throw new globalObject.TypeError("Illegal constructor");
}
substringData(offset, count) {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'substringData' called on an object that is not a valid instance of CharacterData."
);
}
if (arguments.length < 2) {
throw new globalObject.TypeError(
`Failed to execute 'substringData' on 'CharacterData': 2 arguments required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
curArg = conversions["unsigned long"](curArg, {
context: "Failed to execute 'substringData' on 'CharacterData': parameter 1",
globals: globalObject
});
args.push(curArg);
}
{
let curArg = arguments[1];
curArg = conversions["unsigned long"](curArg, {
context: "Failed to execute 'substringData' on 'CharacterData': parameter 2",
globals: globalObject
});
args.push(curArg);
}
return esValue[implSymbol].substringData(...args);
}
appendData(data) {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'appendData' called on an object that is not a valid instance of CharacterData."
);
}
if (arguments.length < 1) {
throw new globalObject.TypeError(
`Failed to execute 'appendData' on 'CharacterData': 1 argument required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
curArg = conversions["DOMString"](curArg, {
context: "Failed to execute 'appendData' on 'CharacterData': parameter 1",
globals: globalObject
});
args.push(curArg);
}
return esValue[implSymbol].appendData(...args);
}
insertData(offset, data) {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'insertData' called on an object that is not a valid instance of CharacterData."
);
}
if (arguments.length < 2) {
throw new globalObject.TypeError(
`Failed to execute 'insertData' on 'CharacterData': 2 arguments required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
curArg = conversions["unsigned long"](curArg, {
context: "Failed to execute 'insertData' on 'CharacterData': parameter 1",
globals: globalObject
});
args.push(curArg);
}
{
let curArg = arguments[1];
curArg = conversions["DOMString"](curArg, {
context: "Failed to execute 'insertData' on 'CharacterData': parameter 2",
globals: globalObject
});
args.push(curArg);
}
return esValue[implSymbol].insertData(...args);
}
deleteData(offset, count) {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'deleteData' called on an object that is not a valid instance of CharacterData."
);
}
if (arguments.length < 2) {
throw new globalObject.TypeError(
`Failed to execute 'deleteData' on 'CharacterData': 2 arguments required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
curArg = conversions["unsigned long"](curArg, {
context: "Failed to execute 'deleteData' on 'CharacterData': parameter 1",
globals: globalObject
});
args.push(curArg);
}
{
let curArg = arguments[1];
curArg = conversions["unsigned long"](curArg, {
context: "Failed to execute 'deleteData' on 'CharacterData': parameter 2",
globals: globalObject
});
args.push(curArg);
}
return esValue[implSymbol].deleteData(...args);
}
replaceData(offset, count, data) {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'replaceData' called on an object that is not a valid instance of CharacterData."
);
}
if (arguments.length < 3) {
throw new globalObject.TypeError(
`Failed to execute 'replaceData' on 'CharacterData': 3 arguments required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
curArg = conversions["unsigned long"](curArg, {
context: "Failed to execute 'replaceData' on 'CharacterData': parameter 1",
globals: globalObject
});
args.push(curArg);
}
{
let curArg = arguments[1];
curArg = conversions["unsigned long"](curArg, {
context: "Failed to execute 'replaceData' on 'CharacterData': parameter 2",
globals: globalObject
});
args.push(curArg);
}
{
let curArg = arguments[2];
curArg = conversions["DOMString"](curArg, {
context: "Failed to execute 'replaceData' on 'CharacterData': parameter 3",
globals: globalObject
});
args.push(curArg);
}
return esValue[implSymbol].replaceData(...args);
}
before() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'before' called on an object that is not a valid instance of CharacterData.");
}
const args = [];
for (let i = 0; i < arguments.length; i++) {
let curArg = arguments[i];
if (Node.is(curArg)) {
curArg = utils.implForWrapper(curArg);
} else {
curArg = conversions["DOMString"](curArg, {
context: "Failed to execute 'before' on 'CharacterData': parameter " + (i + 1),
globals: globalObject
});
}
args.push(curArg);
}
ceReactionsPreSteps_helpers_custom_elements(globalObject);
try {
return esValue[implSymbol].before(...args);
} finally {
ceReactionsPostSteps_helpers_custom_elements(globalObject);
}
}
after() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'after' called on an object that is not a valid instance of CharacterData.");
}
const args = [];
for (let i = 0; i < arguments.length; i++) {
let curArg = arguments[i];
if (Node.is(curArg)) {
curArg = utils.implForWrapper(curArg);
} else {
curArg = conversions["DOMString"](curArg, {
context: "Failed to execute 'after' on 'CharacterData': parameter " + (i + 1),
globals: globalObject
});
}
args.push(curArg);
}
ceReactionsPreSteps_helpers_custom_elements(globalObject);
try {
return esValue[implSymbol].after(...args);
} finally {
ceReactionsPostSteps_helpers_custom_elements(globalObject);
}
}
replaceWith() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'replaceWith' called on an object that is not a valid instance of CharacterData."
);
}
const args = [];
for (let i = 0; i < arguments.length; i++) {
let curArg = arguments[i];
if (Node.is(curArg)) {
curArg = utils.implForWrapper(curArg);
} else {
curArg = conversions["DOMString"](curArg, {
context: "Failed to execute 'replaceWith' on 'CharacterData': parameter " + (i + 1),
globals: globalObject
});
}
args.push(curArg);
}
ceReactionsPreSteps_helpers_custom_elements(globalObject);
try {
return esValue[implSymbol].replaceWith(...args);
} finally {
ceReactionsPostSteps_helpers_custom_elements(globalObject);
}
}
remove() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'remove' called on an object that is not a valid instance of CharacterData.");
}
ceReactionsPreSteps_helpers_custom_elements(globalObject);
try {
return esValue[implSymbol].remove();
} finally {
ceReactionsPostSteps_helpers_custom_elements(globalObject);
}
}
get data() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get data' called on an object that is not a valid instance of CharacterData."
);
}
return esValue[implSymbol]["data"];
}
set data(V) {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'set data' called on an object that is not a valid instance of CharacterData."
);
}
V = conversions["DOMString"](V, {
context: "Failed to set the 'data' property on 'CharacterData': The provided value",
globals: globalObject,
treatNullAsEmptyString: true
});
esValue[implSymbol]["data"] = V;
}
get length() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get length' called on an object that is not a valid instance of CharacterData."
);
}
return esValue[implSymbol]["length"];
}
get previousElementSibling() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get previousElementSibling' called on an object that is not a valid instance of CharacterData."
);
}
return utils.tryWrapperForImpl(esValue[implSymbol]["previousElementSibling"]);
}
get nextElementSibling() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get nextElementSibling' called on an object that is not a valid instance of CharacterData."
);
}
return utils.tryWrapperForImpl(esValue[implSymbol]["nextElementSibling"]);
}
}
Object.defineProperties(CharacterData.prototype, {
substringData: { enumerable: true },
appendData: { enumerable: true },
insertData: { enumerable: true },
deleteData: { enumerable: true },
replaceData: { enumerable: true },
before: { enumerable: true },
after: { enumerable: true },
replaceWith: { enumerable: true },
remove: { enumerable: true },
data: { enumerable: true },
length: { enumerable: true },
previousElementSibling: { enumerable: true },
nextElementSibling: { enumerable: true },
[Symbol.toStringTag]: { value: "CharacterData", configurable: true },
[Symbol.unscopables]: {
value: { before: true, after: true, replaceWith: true, remove: true, __proto__: null },
configurable: true
}
});
ctorRegistry[interfaceName] = CharacterData;
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: CharacterData
});
};
const Impl = require("../nodes/CharacterData-impl.js");

View File

@@ -0,0 +1,168 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const CloseEventInit = require("./CloseEventInit.js");
const implSymbol = utils.implSymbol;
const ctorRegistrySymbol = utils.ctorRegistrySymbol;
const Event = require("./Event.js");
const interfaceName = "CloseEvent";
exports.is = value => {
return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};
exports.isImpl = value => {
return utils.isObject(value) && value instanceof Impl.implementation;
};
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (exports.is(value)) {
return utils.implForWrapper(value);
}
throw new globalObject.TypeError(`${context} is not of type 'CloseEvent'.`);
};
function makeWrapper(globalObject, newTarget) {
let proto;
if (newTarget !== undefined) {
proto = newTarget.prototype;
}
if (!utils.isObject(proto)) {
proto = globalObject[ctorRegistrySymbol]["CloseEvent"].prototype;
}
return Object.create(proto);
}
exports.create = (globalObject, constructorArgs, privateData) => {
const wrapper = makeWrapper(globalObject);
return exports.setup(wrapper, globalObject, constructorArgs, privateData);
};
exports.createImpl = (globalObject, constructorArgs, privateData) => {
const wrapper = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(wrapper);
};
exports._internalSetup = (wrapper, globalObject) => {
Event._internalSetup(wrapper, globalObject);
};
exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
privateData.wrapper = wrapper;
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper;
};
exports.new = (globalObject, newTarget) => {
const wrapper = makeWrapper(globalObject, newTarget);
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: Object.create(Impl.implementation.prototype),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper[implSymbol];
};
const exposed = new Set(["Window", "Worker"]);
exports.install = (globalObject, globalNames) => {
if (!globalNames.some(globalName => exposed.has(globalName))) {
return;
}
const ctorRegistry = utils.initCtorRegistry(globalObject);
class CloseEvent extends globalObject.Event {
constructor(type) {
if (arguments.length < 1) {
throw new globalObject.TypeError(
`Failed to construct 'CloseEvent': 1 argument required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
curArg = conversions["DOMString"](curArg, {
context: "Failed to construct 'CloseEvent': parameter 1",
globals: globalObject
});
args.push(curArg);
}
{
let curArg = arguments[1];
curArg = CloseEventInit.convert(globalObject, curArg, {
context: "Failed to construct 'CloseEvent': parameter 2"
});
args.push(curArg);
}
return exports.setup(Object.create(new.target.prototype), globalObject, args);
}
get wasClean() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get wasClean' called on an object that is not a valid instance of CloseEvent."
);
}
return esValue[implSymbol]["wasClean"];
}
get code() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'get code' called on an object that is not a valid instance of CloseEvent.");
}
return esValue[implSymbol]["code"];
}
get reason() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get reason' called on an object that is not a valid instance of CloseEvent."
);
}
return esValue[implSymbol]["reason"];
}
}
Object.defineProperties(CloseEvent.prototype, {
wasClean: { enumerable: true },
code: { enumerable: true },
reason: { enumerable: true },
[Symbol.toStringTag]: { value: "CloseEvent", configurable: true }
});
ctorRegistry[interfaceName] = CloseEvent;
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: CloseEvent
});
};
const Impl = require("../events/CloseEvent-impl.js");

View File

@@ -0,0 +1,65 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const EventInit = require("./EventInit.js");
exports._convertInherit = (globalObject, obj, ret, { context = "The provided value" } = {}) => {
EventInit._convertInherit(globalObject, obj, ret, { context });
{
const key = "code";
let value = obj === undefined || obj === null ? undefined : obj[key];
if (value !== undefined) {
value = conversions["unsigned short"](value, {
context: context + " has member 'code' that",
globals: globalObject
});
ret[key] = value;
} else {
ret[key] = 0;
}
}
{
const key = "reason";
let value = obj === undefined || obj === null ? undefined : obj[key];
if (value !== undefined) {
value = conversions["USVString"](value, {
context: context + " has member 'reason' that",
globals: globalObject
});
ret[key] = value;
} else {
ret[key] = "";
}
}
{
const key = "wasClean";
let value = obj === undefined || obj === null ? undefined : obj[key];
if (value !== undefined) {
value = conversions["boolean"](value, {
context: context + " has member 'wasClean' that",
globals: globalObject
});
ret[key] = value;
} else {
ret[key] = false;
}
}
};
exports.convert = (globalObject, obj, { context = "The provided value" } = {}) => {
if (obj !== undefined && typeof obj !== "object" && typeof obj !== "function") {
throw new globalObject.TypeError(`${context} is not an object.`);
}
const ret = Object.create(null);
exports._convertInherit(globalObject, obj, ret, { context });
return ret;
};

View File

@@ -0,0 +1,120 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const implSymbol = utils.implSymbol;
const ctorRegistrySymbol = utils.ctorRegistrySymbol;
const CharacterData = require("./CharacterData.js");
const interfaceName = "Comment";
exports.is = value => {
return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};
exports.isImpl = value => {
return utils.isObject(value) && value instanceof Impl.implementation;
};
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (exports.is(value)) {
return utils.implForWrapper(value);
}
throw new globalObject.TypeError(`${context} is not of type 'Comment'.`);
};
function makeWrapper(globalObject, newTarget) {
let proto;
if (newTarget !== undefined) {
proto = newTarget.prototype;
}
if (!utils.isObject(proto)) {
proto = globalObject[ctorRegistrySymbol]["Comment"].prototype;
}
return Object.create(proto);
}
exports.create = (globalObject, constructorArgs, privateData) => {
const wrapper = makeWrapper(globalObject);
return exports.setup(wrapper, globalObject, constructorArgs, privateData);
};
exports.createImpl = (globalObject, constructorArgs, privateData) => {
const wrapper = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(wrapper);
};
exports._internalSetup = (wrapper, globalObject) => {
CharacterData._internalSetup(wrapper, globalObject);
};
exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
privateData.wrapper = wrapper;
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper;
};
exports.new = (globalObject, newTarget) => {
const wrapper = makeWrapper(globalObject, newTarget);
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: Object.create(Impl.implementation.prototype),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper[implSymbol];
};
const exposed = new Set(["Window"]);
exports.install = (globalObject, globalNames) => {
if (!globalNames.some(globalName => exposed.has(globalName))) {
return;
}
const ctorRegistry = utils.initCtorRegistry(globalObject);
class Comment extends globalObject.CharacterData {
constructor() {
const args = [];
{
let curArg = arguments[0];
if (curArg !== undefined) {
curArg = conversions["DOMString"](curArg, {
context: "Failed to construct 'Comment': parameter 1",
globals: globalObject
});
} else {
curArg = "";
}
args.push(curArg);
}
return exports.setup(Object.create(new.target.prototype), globalObject, args);
}
}
Object.defineProperties(Comment.prototype, { [Symbol.toStringTag]: { value: "Comment", configurable: true } });
ctorRegistry[interfaceName] = Comment;
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: Comment
});
};
const Impl = require("../nodes/Comment-impl.js");

View File

@@ -0,0 +1,219 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const CompositionEventInit = require("./CompositionEventInit.js");
const implSymbol = utils.implSymbol;
const ctorRegistrySymbol = utils.ctorRegistrySymbol;
const UIEvent = require("./UIEvent.js");
const interfaceName = "CompositionEvent";
exports.is = value => {
return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};
exports.isImpl = value => {
return utils.isObject(value) && value instanceof Impl.implementation;
};
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (exports.is(value)) {
return utils.implForWrapper(value);
}
throw new globalObject.TypeError(`${context} is not of type 'CompositionEvent'.`);
};
function makeWrapper(globalObject, newTarget) {
let proto;
if (newTarget !== undefined) {
proto = newTarget.prototype;
}
if (!utils.isObject(proto)) {
proto = globalObject[ctorRegistrySymbol]["CompositionEvent"].prototype;
}
return Object.create(proto);
}
exports.create = (globalObject, constructorArgs, privateData) => {
const wrapper = makeWrapper(globalObject);
return exports.setup(wrapper, globalObject, constructorArgs, privateData);
};
exports.createImpl = (globalObject, constructorArgs, privateData) => {
const wrapper = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(wrapper);
};
exports._internalSetup = (wrapper, globalObject) => {
UIEvent._internalSetup(wrapper, globalObject);
};
exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
privateData.wrapper = wrapper;
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper;
};
exports.new = (globalObject, newTarget) => {
const wrapper = makeWrapper(globalObject, newTarget);
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: Object.create(Impl.implementation.prototype),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper[implSymbol];
};
const exposed = new Set(["Window"]);
exports.install = (globalObject, globalNames) => {
if (!globalNames.some(globalName => exposed.has(globalName))) {
return;
}
const ctorRegistry = utils.initCtorRegistry(globalObject);
class CompositionEvent extends globalObject.UIEvent {
constructor(type) {
if (arguments.length < 1) {
throw new globalObject.TypeError(
`Failed to construct 'CompositionEvent': 1 argument required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
curArg = conversions["DOMString"](curArg, {
context: "Failed to construct 'CompositionEvent': parameter 1",
globals: globalObject
});
args.push(curArg);
}
{
let curArg = arguments[1];
curArg = CompositionEventInit.convert(globalObject, curArg, {
context: "Failed to construct 'CompositionEvent': parameter 2"
});
args.push(curArg);
}
return exports.setup(Object.create(new.target.prototype), globalObject, args);
}
initCompositionEvent(typeArg) {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'initCompositionEvent' called on an object that is not a valid instance of CompositionEvent."
);
}
if (arguments.length < 1) {
throw new globalObject.TypeError(
`Failed to execute 'initCompositionEvent' on 'CompositionEvent': 1 argument required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
curArg = conversions["DOMString"](curArg, {
context: "Failed to execute 'initCompositionEvent' on 'CompositionEvent': parameter 1",
globals: globalObject
});
args.push(curArg);
}
{
let curArg = arguments[1];
if (curArg !== undefined) {
curArg = conversions["boolean"](curArg, {
context: "Failed to execute 'initCompositionEvent' on 'CompositionEvent': parameter 2",
globals: globalObject
});
} else {
curArg = false;
}
args.push(curArg);
}
{
let curArg = arguments[2];
if (curArg !== undefined) {
curArg = conversions["boolean"](curArg, {
context: "Failed to execute 'initCompositionEvent' on 'CompositionEvent': parameter 3",
globals: globalObject
});
} else {
curArg = false;
}
args.push(curArg);
}
{
let curArg = arguments[3];
if (curArg !== undefined) {
if (curArg === null || curArg === undefined) {
curArg = null;
} else {
curArg = utils.tryImplForWrapper(curArg);
}
} else {
curArg = null;
}
args.push(curArg);
}
{
let curArg = arguments[4];
if (curArg !== undefined) {
curArg = conversions["DOMString"](curArg, {
context: "Failed to execute 'initCompositionEvent' on 'CompositionEvent': parameter 5",
globals: globalObject
});
} else {
curArg = "";
}
args.push(curArg);
}
return esValue[implSymbol].initCompositionEvent(...args);
}
get data() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get data' called on an object that is not a valid instance of CompositionEvent."
);
}
return esValue[implSymbol]["data"];
}
}
Object.defineProperties(CompositionEvent.prototype, {
initCompositionEvent: { enumerable: true },
data: { enumerable: true },
[Symbol.toStringTag]: { value: "CompositionEvent", configurable: true }
});
ctorRegistry[interfaceName] = CompositionEvent;
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: CompositionEvent
});
};
const Impl = require("../events/CompositionEvent-impl.js");

View File

@@ -0,0 +1,32 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const UIEventInit = require("./UIEventInit.js");
exports._convertInherit = (globalObject, obj, ret, { context = "The provided value" } = {}) => {
UIEventInit._convertInherit(globalObject, obj, ret, { context });
{
const key = "data";
let value = obj === undefined || obj === null ? undefined : obj[key];
if (value !== undefined) {
value = conversions["DOMString"](value, { context: context + " has member 'data' that", globals: globalObject });
ret[key] = value;
} else {
ret[key] = "";
}
}
};
exports.convert = (globalObject, obj, { context = "The provided value" } = {}) => {
if (obj !== undefined && typeof obj !== "object" && typeof obj !== "function") {
throw new globalObject.TypeError(`${context} is not an object.`);
}
const ret = Object.create(null);
exports._convertInherit(globalObject, obj, ret, { context });
return ret;
};

148
node_modules/jsdom/lib/jsdom/living/generated/Crypto.js generated vendored Normal file
View File

@@ -0,0 +1,148 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const implSymbol = utils.implSymbol;
const ctorRegistrySymbol = utils.ctorRegistrySymbol;
const interfaceName = "Crypto";
exports.is = value => {
return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};
exports.isImpl = value => {
return utils.isObject(value) && value instanceof Impl.implementation;
};
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (exports.is(value)) {
return utils.implForWrapper(value);
}
throw new globalObject.TypeError(`${context} is not of type 'Crypto'.`);
};
function makeWrapper(globalObject, newTarget) {
let proto;
if (newTarget !== undefined) {
proto = newTarget.prototype;
}
if (!utils.isObject(proto)) {
proto = globalObject[ctorRegistrySymbol]["Crypto"].prototype;
}
return Object.create(proto);
}
exports.create = (globalObject, constructorArgs, privateData) => {
const wrapper = makeWrapper(globalObject);
return exports.setup(wrapper, globalObject, constructorArgs, privateData);
};
exports.createImpl = (globalObject, constructorArgs, privateData) => {
const wrapper = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(wrapper);
};
exports._internalSetup = (wrapper, globalObject) => {};
exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
privateData.wrapper = wrapper;
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper;
};
exports.new = (globalObject, newTarget) => {
const wrapper = makeWrapper(globalObject, newTarget);
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: Object.create(Impl.implementation.prototype),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper[implSymbol];
};
const exposed = new Set(["Window", "Worker"]);
exports.install = (globalObject, globalNames) => {
if (!globalNames.some(globalName => exposed.has(globalName))) {
return;
}
const ctorRegistry = utils.initCtorRegistry(globalObject);
class Crypto {
constructor() {
throw new globalObject.TypeError("Illegal constructor");
}
getRandomValues(array) {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'getRandomValues' called on an object that is not a valid instance of Crypto."
);
}
if (arguments.length < 1) {
throw new globalObject.TypeError(
`Failed to execute 'getRandomValues' on 'Crypto': 1 argument required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
if (ArrayBuffer.isView(curArg)) {
curArg = conversions["ArrayBufferView"](curArg, {
context: "Failed to execute 'getRandomValues' on 'Crypto': parameter 1",
globals: globalObject
});
} else {
throw new globalObject.TypeError(
"Failed to execute 'getRandomValues' on 'Crypto': parameter 1" + " is not of any supported type."
);
}
args.push(curArg);
}
return esValue[implSymbol].getRandomValues(...args);
}
randomUUID() {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError("'randomUUID' called on an object that is not a valid instance of Crypto.");
}
return esValue[implSymbol].randomUUID();
}
}
Object.defineProperties(Crypto.prototype, {
getRandomValues: { enumerable: true },
randomUUID: { enumerable: true },
[Symbol.toStringTag]: { value: "Crypto", configurable: true }
});
ctorRegistry[interfaceName] = Crypto;
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: Crypto
});
};
const Impl = require("../crypto/Crypto-impl.js");

View File

@@ -0,0 +1,34 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (typeof value !== "function") {
throw new globalObject.TypeError(context + " is not a function");
}
function invokeTheCallbackFunction() {
const thisArg = utils.tryWrapperForImpl(this);
let callResult;
callResult = Reflect.apply(value, thisArg, []);
callResult = conversions["any"](callResult, { context: context, globals: globalObject });
return callResult;
}
invokeTheCallbackFunction.construct = () => {
let callResult = Reflect.construct(value, []);
callResult = conversions["any"](callResult, { context: context, globals: globalObject });
return callResult;
};
invokeTheCallbackFunction[utils.wrapperSymbol] = value;
invokeTheCallbackFunction.objectReference = value;
return invokeTheCallbackFunction;
};

View File

@@ -0,0 +1,267 @@
"use strict";
const conversions = require("webidl-conversions");
const utils = require("./utils.js");
const CustomElementConstructor = require("./CustomElementConstructor.js");
const ElementDefinitionOptions = require("./ElementDefinitionOptions.js");
const ceReactionsPreSteps_helpers_custom_elements = require("../helpers/custom-elements.js").ceReactionsPreSteps;
const ceReactionsPostSteps_helpers_custom_elements = require("../helpers/custom-elements.js").ceReactionsPostSteps;
const Node = require("./Node.js");
const implSymbol = utils.implSymbol;
const ctorRegistrySymbol = utils.ctorRegistrySymbol;
const interfaceName = "CustomElementRegistry";
exports.is = value => {
return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
};
exports.isImpl = value => {
return utils.isObject(value) && value instanceof Impl.implementation;
};
exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
if (exports.is(value)) {
return utils.implForWrapper(value);
}
throw new globalObject.TypeError(`${context} is not of type 'CustomElementRegistry'.`);
};
function makeWrapper(globalObject, newTarget) {
let proto;
if (newTarget !== undefined) {
proto = newTarget.prototype;
}
if (!utils.isObject(proto)) {
proto = globalObject[ctorRegistrySymbol]["CustomElementRegistry"].prototype;
}
return Object.create(proto);
}
exports.create = (globalObject, constructorArgs, privateData) => {
const wrapper = makeWrapper(globalObject);
return exports.setup(wrapper, globalObject, constructorArgs, privateData);
};
exports.createImpl = (globalObject, constructorArgs, privateData) => {
const wrapper = exports.create(globalObject, constructorArgs, privateData);
return utils.implForWrapper(wrapper);
};
exports._internalSetup = (wrapper, globalObject) => {};
exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
privateData.wrapper = wrapper;
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: new Impl.implementation(globalObject, constructorArgs, privateData),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper;
};
exports.new = (globalObject, newTarget) => {
const wrapper = makeWrapper(globalObject, newTarget);
exports._internalSetup(wrapper, globalObject);
Object.defineProperty(wrapper, implSymbol, {
value: Object.create(Impl.implementation.prototype),
configurable: true
});
wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
if (Impl.init) {
Impl.init(wrapper[implSymbol]);
}
return wrapper[implSymbol];
};
const exposed = new Set(["Window"]);
exports.install = (globalObject, globalNames) => {
if (!globalNames.some(globalName => exposed.has(globalName))) {
return;
}
const ctorRegistry = utils.initCtorRegistry(globalObject);
class CustomElementRegistry {
constructor() {
throw new globalObject.TypeError("Illegal constructor");
}
define(name, constructor) {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'define' called on an object that is not a valid instance of CustomElementRegistry."
);
}
if (arguments.length < 2) {
throw new globalObject.TypeError(
`Failed to execute 'define' on 'CustomElementRegistry': 2 arguments required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
curArg = conversions["DOMString"](curArg, {
context: "Failed to execute 'define' on 'CustomElementRegistry': parameter 1",
globals: globalObject
});
args.push(curArg);
}
{
let curArg = arguments[1];
curArg = CustomElementConstructor.convert(globalObject, curArg, {
context: "Failed to execute 'define' on 'CustomElementRegistry': parameter 2"
});
args.push(curArg);
}
{
let curArg = arguments[2];
curArg = ElementDefinitionOptions.convert(globalObject, curArg, {
context: "Failed to execute 'define' on 'CustomElementRegistry': parameter 3"
});
args.push(curArg);
}
ceReactionsPreSteps_helpers_custom_elements(globalObject);
try {
return esValue[implSymbol].define(...args);
} finally {
ceReactionsPostSteps_helpers_custom_elements(globalObject);
}
}
get(name) {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'get' called on an object that is not a valid instance of CustomElementRegistry."
);
}
if (arguments.length < 1) {
throw new globalObject.TypeError(
`Failed to execute 'get' on 'CustomElementRegistry': 1 argument required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
curArg = conversions["DOMString"](curArg, {
context: "Failed to execute 'get' on 'CustomElementRegistry': parameter 1",
globals: globalObject
});
args.push(curArg);
}
return esValue[implSymbol].get(...args);
}
getName(constructor) {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'getName' called on an object that is not a valid instance of CustomElementRegistry."
);
}
if (arguments.length < 1) {
throw new globalObject.TypeError(
`Failed to execute 'getName' on 'CustomElementRegistry': 1 argument required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
curArg = CustomElementConstructor.convert(globalObject, curArg, {
context: "Failed to execute 'getName' on 'CustomElementRegistry': parameter 1"
});
args.push(curArg);
}
return esValue[implSymbol].getName(...args);
}
whenDefined(name) {
try {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'whenDefined' called on an object that is not a valid instance of CustomElementRegistry."
);
}
if (arguments.length < 1) {
throw new globalObject.TypeError(
`Failed to execute 'whenDefined' on 'CustomElementRegistry': 1 argument required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
curArg = conversions["DOMString"](curArg, {
context: "Failed to execute 'whenDefined' on 'CustomElementRegistry': parameter 1",
globals: globalObject
});
args.push(curArg);
}
return utils.tryWrapperForImpl(esValue[implSymbol].whenDefined(...args));
} catch (e) {
return globalObject.Promise.reject(e);
}
}
upgrade(root) {
const esValue = this !== null && this !== undefined ? this : globalObject;
if (!exports.is(esValue)) {
throw new globalObject.TypeError(
"'upgrade' called on an object that is not a valid instance of CustomElementRegistry."
);
}
if (arguments.length < 1) {
throw new globalObject.TypeError(
`Failed to execute 'upgrade' on 'CustomElementRegistry': 1 argument required, but only ${arguments.length} present.`
);
}
const args = [];
{
let curArg = arguments[0];
curArg = Node.convert(globalObject, curArg, {
context: "Failed to execute 'upgrade' on 'CustomElementRegistry': parameter 1"
});
args.push(curArg);
}
ceReactionsPreSteps_helpers_custom_elements(globalObject);
try {
return esValue[implSymbol].upgrade(...args);
} finally {
ceReactionsPostSteps_helpers_custom_elements(globalObject);
}
}
}
Object.defineProperties(CustomElementRegistry.prototype, {
define: { enumerable: true },
get: { enumerable: true },
getName: { enumerable: true },
whenDefined: { enumerable: true },
upgrade: { enumerable: true },
[Symbol.toStringTag]: { value: "CustomElementRegistry", configurable: true }
});
ctorRegistry[interfaceName] = CustomElementRegistry;
Object.defineProperty(globalObject, interfaceName, {
configurable: true,
writable: true,
value: CustomElementRegistry
});
};
const Impl = require("../custom-elements/CustomElementRegistry-impl.js");

Some files were not shown because too many files have changed in this diff Show More