File: /var/www/zaklada/html/node_modules/jsdom/lib/jsdom/utils.js
"use strict";
const path = require("path");
const URL = require("whatwg-url-compat").createURLConstructor();
const domSymbolTree = require("./living/helpers/internal-constants").domSymbolTree;
const SYMBOL_TREE_POSITION = require("symbol-tree").TreePosition;
exports.URL = URL;
exports.toFileUrl = function (fileName) {
// Beyond just the `path.resolve`, this is mostly for the benefit of Windows,
// where we need to convert "\" to "/" and add an extra "/" prefix before the
// drive letter.
let pathname = path.resolve(process.cwd(), fileName).replace(/\\/g, "/");
if (pathname[0] !== "/") {
pathname = "/" + pathname;
}
// path might contain spaces, so convert those to %20
return "file://" + encodeURI(pathname);
};
/**
* Define a setter on an object
*
* This method replaces any existing setter but leaves getters in place.
*
* - `object` {Object} the object to define the setter on
* - `property` {String} the name of the setter
* - `setterFn` {Function} the setter
*/
exports.defineSetter = function defineSetter(object, property, setterFn) {
const descriptor = Object.getOwnPropertyDescriptor(object, property) || {
configurable: true,
enumerable: true
};
descriptor.set = setterFn;
Object.defineProperty(object, property, descriptor);
};
/**
* Define a getter on an object
*
* This method replaces any existing getter but leaves setters in place.
*
* - `object` {Object} the object to define the getter on
* - `property` {String} the name of the getter
* - `getterFn` {Function} the getter
*/
exports.defineGetter = function defineGetter(object, property, getterFn) {
const descriptor = Object.getOwnPropertyDescriptor(object, property) || {
configurable: true,
enumerable: true
};
descriptor.get = getterFn;
Object.defineProperty(object, property, descriptor);
};
/**
* Create an object with the given prototype
*
* Optionally augment the created object.
*
* - `prototype` {Object} the created object's prototype
* - `[properties]` {Object} properties to attach to the created object
*/
exports.createFrom = function createFrom(prototype, properties) {
properties = properties || {};
const descriptors = {};
for (const name of Object.getOwnPropertyNames(properties)) {
descriptors[name] = Object.getOwnPropertyDescriptor(properties, name);
}
return Object.create(prototype, descriptors);
};
/**
* Create an inheritance relationship between two classes
*
* Optionally augment the inherited prototype.
*
* - `Superclass` {Function} the inherited class
* - `Subclass` {Function} the inheriting class
* - `[properties]` {Object} properties to attach to the inherited prototype
*/
exports.inheritFrom = function inheritFrom(Superclass, Subclass, properties) {
properties = properties || {};
Object.defineProperty(properties, "constructor", {
value: Subclass,
writable: true,
configurable: true
});
Subclass.prototype = exports.createFrom(Superclass.prototype, properties);
};
/**
* Define a set of properties on an object, by copying the property descriptors
* from the original object.
*
* - `object` {Object} the target object
* - `properties` {Object} the source from which to copy property descriptors
*/
exports.define = function define(object, properties) {
for (const name of Object.getOwnPropertyNames(properties)) {
const propDesc = Object.getOwnPropertyDescriptor(properties, name);
Object.defineProperty(object, name, propDesc);
}
};
/**
* Define a list of constants on a constructor and its .prototype
*
* - `Constructor` {Function} the constructor to define the constants on
* - `propertyMap` {Object} key/value map of properties to define
*/
exports.addConstants = function addConstants(Constructor, propertyMap) {
for (const property in propertyMap) {
const value = propertyMap[property];
addConstant(Constructor, property, value);
addConstant(Constructor.prototype, property, value);
}
};
function addConstant(object, property, value) {
Object.defineProperty(object, property, {
configurable: false,
enumerable: true,
writable: false,
value
});
}
let memoizeQueryTypeCounter = 0;
/**
* Returns a version of a method that memoizes specific types of calls on the object
*
* - `fn` {Function} the method to be memozied
*/
exports.memoizeQuery = function memoizeQuery(fn) {
// Only memoize query functions with arity <= 2
if (fn.length > 2) {
return fn;
}
const type = memoizeQueryTypeCounter++;
return function () {
if (!this._memoizedQueries) {
return fn.apply(this, arguments);
}
if (!this._memoizedQueries[type]) {
this._memoizedQueries[type] = Object.create(null);
}
let key;
if (arguments.length === 1 && typeof arguments[0] === "string") {
key = arguments[0];
} else if (arguments.length === 2 && typeof arguments[0] === "string" && typeof arguments[1] === "string") {
key = arguments[0] + "::" + arguments[1];
} else {
return fn.apply(this, arguments);
}
if (!(key in this._memoizedQueries[type])) {
this._memoizedQueries[type][key] = fn.apply(this, arguments);
}
return this._memoizedQueries[type][key];
};
};
exports.resolveHref = function resolveHref(baseUrl, href) {
try {
return new URL(href, baseUrl).href;
} catch (e) {
// can't throw since this utility is basically used everywhere
// do what the spec says regarding anchor tags: just don't parse it
// https://url.spec.whatwg.org/#dom-urlutils-href
return href;
}
};
exports.mapper = function (parent, filter, recursive) {
function skipRoot(node) {
return node !== parent && (!filter || filter(node));
}
return () => {
if (recursive !== false) { // default is not recursive
return domSymbolTree.treeToArray(parent, { filter: skipRoot });
}
return domSymbolTree.childrenToArray(parent, { filter });
};
};
function isValidAbsoluteURL(str) {
try {
/* eslint-disable no-new */
new URL(str);
/* eslint-enable no-new */
// If we can parse it, it's a valid absolute URL.
return true;
} catch (e) {
return false;
}
}
exports.isValidTargetOrigin = function (str) {
return str === "*" || str === "/" || isValidAbsoluteURL(str);
};
exports.simultaneousIterators = function* (first, second) {
for (;;) {
const firstResult = first.next();
const secondResult = second.next();
if (firstResult.done && secondResult.done) {
return;
}
yield [
firstResult.done ? null : firstResult.value,
secondResult.done ? null : secondResult.value
];
}
};
exports.treeOrderSorter = function (a, b) {
const compare = domSymbolTree.compareTreePosition(a, b);
if (compare & SYMBOL_TREE_POSITION.PRECEDING) { // b is preceding a
return 1;
}
if (compare & SYMBOL_TREE_POSITION.FOLLOWING) {
return -1;
}
// disconnected or equal:
return 0;
};
exports.lengthFromProperties = function (arrayLike) {
let max = -1;
const keys = Object.keys(arrayLike);
const highestKeyIndex = keys.length - 1;
// Abuses a v8 implementation detail for a very fast case
// (if this implementation detail changes, this method will still
// return correct results)
/* eslint-disable eqeqeq */
if (highestKeyIndex == keys[highestKeyIndex]) { // not ===
/* eslint-enable eqeqeq */
return keys.length;
}
for (let i = highestKeyIndex; i >= 0; --i) {
const asNumber = Number(keys[i]);
if (!Number.isNaN(asNumber) && asNumber > max) {
max = asNumber;
}
}
return max + 1;
};
const base64Regexp = /^(?:[A-Z0-9+\/]{4})*(?:[A-Z0-9+\/]{2}==|[A-Z0-9+\/]{3}=|[A-Z0-9+\/]{4})$/i;
exports.parseDataUrl = function parseDataUrl(url) {
const urlParts = url.match(/^data:(.+?)(?:;(base64))?,(.*)$/);
let buffer;
if (urlParts[2] === "base64") {
if (!base64Regexp.test(urlParts[3])) {
throw new Error("Not a base64 string");
}
buffer = new Buffer(urlParts[3], "base64");
} else {
buffer = new Buffer(urlParts[3]);
}
return { buffer, type: urlParts[1] };
};