Update dashboard, kb, memory +4 more (+28 ~18 -1)
This commit is contained in:
373
node_modules/jsdom/lib/api.js
generated
vendored
Normal file
373
node_modules/jsdom/lib/api.js
generated
vendored
Normal 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;
|
||||
Reference in New Issue
Block a user