Innovenergy_trunk/frontend/node_modules/testcafe-hammerhead/lib/processing/script/index.js

153 lines
6.8 KiB
JavaScript
Raw Normal View History

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.processScript = exports.isScriptProcessed = void 0;
const transform_1 = __importDefault(require("./transform"));
const instruction_1 = __importDefault(require("./instruction"));
const header_1 = require("./header");
const acorn_hammerhead_1 = require("acorn-hammerhead");
const esotope_hammerhead_1 = require("esotope-hammerhead");
const regexp_escape_1 = __importDefault(require("../../utils/regexp-escape"));
const get_bom_1 = __importDefault(require("../../utils/get-bom"));
const HTML_COMMENT_RE = /(^|\n)\s*<!--[^\n]*(\n|$)/g;
const OBJECT_RE = /^\s*\{.*\}\s*$/;
const TRAILING_SEMICOLON_RE = /;\s*$/;
const OBJECT_WRAPPER_RE = /^\s*\((.*)\);\s*$/;
const SOURCEMAP_RE = /(?:\/\/[@#][ \t]+sourceMappingURL=([^\s'"]+?)[ \t]*$)/gm;
const PROCESSED_SCRIPT_RE = new RegExp([
(0, regexp_escape_1.default)(instruction_1.default.getLocation),
(0, regexp_escape_1.default)(instruction_1.default.setLocation),
(0, regexp_escape_1.default)(instruction_1.default.getProperty),
(0, regexp_escape_1.default)(instruction_1.default.setProperty),
(0, regexp_escape_1.default)(instruction_1.default.callMethod),
(0, regexp_escape_1.default)(instruction_1.default.processScript),
(0, regexp_escape_1.default)(instruction_1.default.processHtml),
(0, regexp_escape_1.default)(instruction_1.default.getPostMessage),
(0, regexp_escape_1.default)(instruction_1.default.getProxyUrl),
].join('|'));
const PARSING_OPTIONS = {
allowReturnOutsideFunction: true,
allowImportExportEverywhere: true,
ecmaVersion: 13,
};
// Code pre/post-processing
function removeHtmlComments(code) {
// NOTE: The JS parser removes the line that follows'<!--'. (T226589)
do
code = code.replace(HTML_COMMENT_RE, '\n');
while (HTML_COMMENT_RE.test(code));
return code;
}
function preprocess(code) {
const bom = (0, get_bom_1.default)(code);
let preprocessed = bom ? code.substring(bom.length) : code;
preprocessed = (0, header_1.remove)(preprocessed);
preprocessed = removeSourceMap(preprocessed);
return { bom, preprocessed };
}
function removeSourceMap(code) {
return code.replace(SOURCEMAP_RE, '');
}
function postprocess(processed, withHeader, bom, strictMode, swScopeHeaderValue, proxyless, workerSettings) {
// NOTE: If the 'use strict' directive is not in the beginning of the file, it is ignored.
// As we insert our header in the beginning of the script, we must put a new 'use strict'
// before the header, otherwise it will be ignored.
if (withHeader)
processed = (0, header_1.add)(processed, strictMode, swScopeHeaderValue, proxyless, workerSettings);
return bom ? bom + processed : processed;
}
// Parse/generate code
function removeTrailingSemicolon(processed, src) {
return TRAILING_SEMICOLON_RE.test(src) ? processed : processed.replace(TRAILING_SEMICOLON_RE, '');
}
function getAst(src, isObject) {
// NOTE: In case of objects (e.g.eval('{ 1: 2}')) without wrapping
// object will be parsed as label. To avoid this we parenthesize src
src = isObject ? `(${src})` : src;
try {
return (0, acorn_hammerhead_1.parse)(src, PARSING_OPTIONS);
}
catch (err) {
return null;
}
}
function getCode(ast, src) {
const code = (0, esotope_hammerhead_1.generate)(ast, {
format: {
quotes: 'double',
escapeless: true,
compact: true,
},
});
return src ? removeTrailingSemicolon(code, src) : code;
}
// Analyze code
function analyze(code) {
let isObject = OBJECT_RE.test(code);
let ast = getAst(code, isObject);
// NOTE: `{ const a = 'foo'; }` edge case
if (!ast && isObject) {
ast = getAst(code, false);
isObject = false;
}
return { ast, isObject };
}
function isArrayDataScript(ast) {
const firstChild = ast.body[0];
return ast.body.length === 1 &&
firstChild.type === esotope_hammerhead_1.Syntax.ExpressionStatement &&
firstChild.expression.type === esotope_hammerhead_1.Syntax.ArrayExpression;
}
function isStrictMode(ast) {
if (ast.body.length) {
const firstChild = ast.body[0];
if (firstChild.type === esotope_hammerhead_1.Syntax.ExpressionStatement && firstChild.expression.type === esotope_hammerhead_1.Syntax.Literal)
return firstChild.expression.value === 'use strict';
}
return false;
}
function applyChanges(script, changes, isObject) {
const indexOffset = isObject ? -1 : 0;
const chunks = [];
let index = 0;
if (!changes.length)
return script;
changes.sort((a, b) => (a.start - b.start) || (a.end - b.end) || // eslint-disable-line @typescript-eslint/no-extra-parens
((a.node.type === esotope_hammerhead_1.Syntax.VariableDeclaration ? 0 : 1) - (b.node.type === esotope_hammerhead_1.Syntax.VariableDeclaration ? 0 : 1))); // eslint-disable-line @typescript-eslint/no-extra-parens
for (const change of changes) {
const changeStart = change.start + indexOffset;
const changeEnd = change.end + indexOffset;
const parentheses = change.node.type === esotope_hammerhead_1.Syntax.SequenceExpression &&
change.parentType !== esotope_hammerhead_1.Syntax.ExpressionStatement &&
change.parentType !== esotope_hammerhead_1.Syntax.SequenceExpression;
chunks.push(script.substring(index, changeStart));
chunks.push(parentheses ? '(' : ' ');
chunks.push(getCode(change.node, script.substring(changeStart, changeEnd)));
chunks.push(parentheses ? ')' : ' ');
index += changeEnd - index;
}
chunks.push(script.substring(index));
return chunks.join('');
}
function isScriptProcessed(code) {
return PROCESSED_SCRIPT_RE.test(code);
}
exports.isScriptProcessed = isScriptProcessed;
function processScript(src, withHeader = false, wrapLastExprWithProcessHtml = false, resolver, swScopeHeaderValue, proxyless, workerSettings) {
const { bom, preprocessed } = preprocess(src);
const withoutHtmlComments = removeHtmlComments(preprocessed);
const { ast, isObject } = analyze(withoutHtmlComments);
if (!ast)
return src;
withHeader = withHeader && !isObject && !isArrayDataScript(ast);
const changes = proxyless ? [] : (0, transform_1.default)(ast, wrapLastExprWithProcessHtml, resolver);
let processed = changes.length ? applyChanges(withoutHtmlComments, changes, isObject) : preprocessed;
processed = postprocess(processed, withHeader, bom, isStrictMode(ast), swScopeHeaderValue, proxyless, workerSettings);
if (isObject)
processed = processed.replace(OBJECT_WRAPPER_RE, '$1');
return processed;
}
exports.processScript = processScript;