ApplicationInsights-JS/tools/updateDistEsm/updateDistEsm.js

364 строки
12 KiB
JavaScript

import dynamicRemove from "@microsoft/dynamicproto-js/tools/rollup";
import MagicString from "magic-string";
const fs = require("fs");
const globby = require("globby");
// Remap tslib functions to shim v2.0.0 functions
const remapTsLibFuncs = {
__extends: "__extendsFn",
__assign: "__assignFn",
__rest: "__restFn",
__spreadArray: "__spreadArrayFn",
__spreadArrays: "__spreadArraysFn",
__decorate: "__decorateFn",
__param: "__paramFn",
__metadata: "__metadataFn",
__values: "__valuesFn",
__read: "__readFn",
__createBinding: "__createBindingFn",
__importDefault: "__importDefaultFn",
__importStar: "__importStarFn",
__exportStar: "__exportStarFn",
__makeTemplateObject: "__makeTemplateObjectFn"
};
// You can use the following site to validate the resulting map file is valid
// http://sokra.github.io/source-map-visualization/#custom
// Function to remove the @DynamicProtoStubs and rewrite the headers for the dist-es5 files
const getLines = (theValue) => {
var value = "" + theValue;
var lines = [];
var idx = 0;
var startIdx = 0;
while (idx < value.length) {
// Skip blank lines
while (
idx < value.length &&
(value[idx] === "\n" || value[idx] === "\r")
) {
idx++;
}
startIdx = idx;
while (
idx < value.length &&
!(value[idx] === "\n" || value[idx] === "\r")
) {
idx++;
}
var len = idx - startIdx;
if (len > 0) {
var line = value.substring(startIdx, idx);
if (line.trim() !== "") {
lines.push({
value: line,
idx: startIdx,
len: len
});
}
}
}
return lines;
};
function replaceTsLibImports(orgSrc, src, theString) {
// replace tslib import usage with "import { xxx, xxx } from "tslib";
const detectTsLibUsage = /import[\s]*\{([^}]*)\}[\s]*from[\s]*\"tslib\";/g;
let matches = detectTsLibUsage.exec(orgSrc);
while (matches != null) {
let newImports = [];
let imports = matches[1];
let tokens = imports.trim().split(",");
tokens.forEach((token) => {
let theToken = token.trim();
let remapKey = remapTsLibFuncs[theToken];
if (!remapKey) {
throw (
'Unsupported tslib function "' +
theToken +
'" detected from -- ' +
matches[0] +
""
);
}
newImports.push(remapKey + " as " + theToken);
});
let newImport =
"import { " +
newImports.join(", ") +
' } from "@microsoft/applicationinsights-shims";';
var idx = orgSrc.indexOf(matches[0]);
if (idx !== -1) {
console.log(`Replacing [${matches[0]}] with [${newImport}]`);
theString.overwrite(idx, idx + matches[0].length, newImport);
src = src.replace(matches[0], newImport);
}
// Find next
matches = detectTsLibUsage.exec(orgSrc);
}
return src;
}
function replaceTsLibStarImports(orgSrc, src, theString) {
// replace tslib import usage with "import { xxx, xxx } from "tslib";
const detectTsLibUsage =
/import[\s]*\*[\s]*as[\s]*([^\s]*)[\s]*from[\s]*\"tslib\";/g;
let matches = detectTsLibUsage.exec(orgSrc);
while (matches != null) {
let newImports = [];
let importPrefix = matches[1].trim();
let importLen = importPrefix.length + 1;
let idx = orgSrc.indexOf(importPrefix + ".");
while (idx !== -1) {
let funcEnd = orgSrc.indexOf("(", idx + importLen);
if (funcEnd !== -1) {
let funcName = orgSrc.substring(idx + importLen, funcEnd);
let newImport = remapTsLibFuncs[funcName];
if (!newImport) {
throw (
'Unsupported tslib function "' +
orgSrc.substring(idx, funcEnd) +
'" detected from -- ' +
matches[0]
);
}
// Add new import, if not already present
if (newImports.indexOf(newImport) == -1) {
newImports.push(newImport);
}
let matchedValue = orgSrc.substring(idx, funcEnd + 1);
let newValue = newImport + "(";
console.log(
`Replacing Usage [${matchedValue}] with [${newValue}]`
);
theString.overwrite(idx, idx + matchedValue.length, newValue);
// replace in the new source output as well
src = src.replace(matchedValue, newValue);
}
// Find next usage
idx = orgSrc.indexOf(importPrefix + ".", idx + importLen);
}
let newImport =
"import { " +
newImports.join(", ") +
' } from "@microsoft/applicationinsights-shims";';
idx = orgSrc.indexOf(matches[0]);
console.log(`Replacing [${matches[0]}] with [${newImport}]`);
theString.overwrite(idx, idx + matches[0].length, newImport);
src = src.replace(matches[0], newImport);
// Find next
matches = detectTsLibUsage.exec(orgSrc);
}
return src;
}
function removeDynamicProtoStubs(orgSrc, src, theString, inputFile) {
const dynRemove = dynamicRemove();
var result = dynRemove.transform(orgSrc, inputFile);
if (result !== null && result.code) {
src = result.code;
console.log("Prototypes removed...");
// Figure out removed lines
var orgLines = getLines(orgSrc);
var newLines = getLines(result.code);
var line = 0;
var newLine = 0;
while (line < orgLines.length) {
var matchLine = orgLines[line];
var matchNewLine = newLines[newLine];
var replaceText = "";
line++;
if (matchLine.value === matchNewLine.value) {
newLine++;
} else {
console.log("Line Changed: " + matchLine.value);
var endFound = false;
var endLine = 0;
// Skip over removed lines (There may be more than 1 function being removed)
for (
var nextLp = 0;
endFound === false && newLine + nextLp < newLines.length;
nextLp++
) {
if (newLine + nextLp < newLines.length) {
for (var lp = 0; line + lp < orgLines.length; lp++) {
if (
orgLines[line + lp].value ===
newLines[newLine + nextLp].value
) {
endFound = true;
for (var i = 0; i < nextLp; i++) {
if (replaceText.length) {
replaceText += "\n";
}
replaceText += newLines[newLine + i].value;
}
endLine = line + lp;
newLine = newLine + nextLp;
break;
}
}
}
}
if (endFound) {
console.log(
"Detected Removed lines " + line + " to " + endLine
);
theString.overwrite(
matchLine.idx,
orgLines[endLine - 1].idx + orgLines[endLine - 1].len,
replaceText
);
line = endLine;
} else {
throw "Missing line - " + matchLine.value;
}
}
}
}
return src;
}
function fixIEDynamicProtoUsage(orgSrc, src, theString) {
// find all "dynamicProto(<classname>," usages
// Then find all "class <classname> " usages and append a static variable after the name
const dynamicProtoUsage = /dynamicProto\s*\(\s*(\w*)\s*,/g;
let matches = dynamicProtoUsage.exec(orgSrc);
while (matches != null) {
let className = matches[1].trim();
let hasProperty = new RegExp("^\\s*" + className + "\\.\\w+\\s*", "gm");
let hasPropertyMatches = hasProperty.exec(src);
if (!hasPropertyMatches) {
if (orgSrc.indexOf(" return " + className + ";") === -1) {
throw "return " + className + "; -- doesn't exist!!! -- " + orgSrc;
}
let classRegEx = new RegExp("^\\s*return\\s+" + className + ";", "gm");
let classMatches = classRegEx.exec(orgSrc);
if (!classMatches) {
throw ('Unable to locate class definition for "' + className + '" using ' + classRegEx + ' detected from -- ' + matches[0] + ' -- ' + classMatches + " in \n" + orgSrc);
}
let newClass =
"\n // This is a workaround for an IE bug when using dynamicProto() with classes that don't have any" +
"\n // non-dynamic functions or static properties/functions when using uglify-js to minify the resulting code." +
"\n " + className + ".__ieDyn=1;" +
"\n" + classMatches[0];
var idx = orgSrc.indexOf(classMatches[0]);
if (idx !== -1) {
console.log(`Replacing [${classMatches[0]}] with [${newClass}]`);
theString.overwrite(idx, idx + classMatches[0].length, newClass);
src = src.replace(classMatches[0], newClass);
}
} else {
console.log("dynamicProto class has property or function -- " + hasProperty + " found " + hasPropertyMatches[0]);
}
// Find next
matches = dynamicProtoUsage.exec(orgSrc);
}
return src;
}
const updateDistEsmFiles = (
replaceValues,
banner,
replaceTsLib = true,
removeDynamic = true,
buildPath = "dist-es5"
) => {
console.log(`UpdateDistEsmFiles: ./${buildPath}/**/*.js`);
if (!fs.existsSync(`./${buildPath}`)) {
console.error(`Build path does not exist ./${buildPath} - from:${process.cwd()}`);
process.exit(10);
}
const files = globby.sync(`./${buildPath}/**/*.js`);
files.map((inputFile) => {
console.log("Loading - " + inputFile);
var src = fs.readFileSync(inputFile, "utf8");
var mapFile;
if (inputFile.endsWith(".js")) {
mapFile = inputFile + ".map";
}
var orgSrc = src;
var theString = new MagicString(orgSrc);
if (removeDynamic) {
src = removeDynamicProtoStubs(orgSrc, src, theString, inputFile);
}
if (replaceTsLib) {
// replace any tslib imports with the shims module versions
src = replaceTsLibImports(orgSrc, src, theString);
src = replaceTsLibStarImports(orgSrc, src, theString);
}
src = fixIEDynamicProtoUsage(orgSrc, src, theString);
// Replace the header
Object.keys(replaceValues).forEach((value) => {
src = src.replace(value, replaceValues[value]);
var idx = orgSrc.indexOf(value);
if (idx !== -1) {
theString.overwrite(
idx,
idx + value.length,
replaceValues[value]
);
}
});
// Rewrite the file
// Remove any force banner from the file
let replaceBanner = banner.replace("/*!", "/*");
theString.prepend(replaceBanner + "\n");
src = replaceBanner + "\n" + src;
src = src.trim();
if (orgSrc !== src) {
fs.writeFileSync(inputFile, src);
if (mapFile) {
var newMap = theString.generateMap({
source: inputFile.toString(),
file: mapFile,
includeContent: true,
hires: false
});
console.log("Rewriting Map file - " + mapFile);
fs.writeFileSync(mapFile, newMap.toString());
}
}
});
};
export { updateDistEsmFiles };