UNPKG

webpack-strip-log-loader

Version:
428 lines 38.2 kB
"use strict"; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const ts = __importStar(require("byots")); const fs = __importStar(require("fs")); const loader_utils_1 = require("loader-utils"); const path = __importStar(require("path")); const tmp = __importStar(require("tmp")); const logger = __importStar(require("loglevel")); const minimatch_1 = __importDefault(require("minimatch")); const flatMap = require('array.prototype.flatmap'); flatMap.shim(); if (process.env.NODE_ENV === 'trace') { logger.setDefaultLevel(logger.levels.TRACE); } else if (process.env.NODE_ENV === 'debug') { logger.setDefaultLevel(logger.levels.DEBUG); } else { logger.setDefaultLevel(logger.levels.ERROR); } const utils_1 = require("./utils"); const ignoreRegex = /^\/\/(\W*)strip-log(\W*)$/i; function isNodeCommentTrigger(node, sourceFile) { const comments = utils_1.getComments(node, sourceFile.getFullText(), true); const matchingComment = comments.find(tmpComment => { return ignoreRegex.test(tmpComment); }); if (matchingComment !== undefined) { return true; } else { return false; } } class PluginLoader { constructor(loaderContext, sourceText) { this.restrictedSymbols = new Set(); this.restrictedExpressions = new Set(); this.sourceText = sourceText; let rawOptions = loader_utils_1.getOptions(loaderContext); if (rawOptions === null) { rawOptions = {}; } rawOptions.modules = rawOptions.modules || []; this.options = rawOptions; this.initTypescriptCompiler(); } process() { this.findAllImportClauses(); this.findAllRequireStatements(); this.findExplicitlyRestrictedSymbols(); this.findAllSymbolsAndExpressions(); const targetText = this.returntransformedSource(); this.cleanup(); return targetText; } initTypescriptCompiler() { logger.trace(`Input file content: \n ${this.sourceText}`); this.tmpFile = tmp.fileSync({ postfix: '.js', }); fs.writeFileSync(this.tmpFile.fd, this.sourceText); this.tsProgram = ts.createProgram([this.tmpFile.name], { allowJs: true, noResolve: true, }); this.tsChecker = this.tsProgram.getTypeChecker(); for (const tmpSourceFile of this.tsProgram.getSourceFiles()) { if (!tmpSourceFile.isDeclarationFile) { if (path.normalize(tmpSourceFile.fileName) === path.normalize(this.tmpFile.name)) { this.mainSourceFile = tmpSourceFile; } } } if (this.mainSourceFile === undefined) { this.cleanup(); throw new TypeError('Source file not found'); } } findAllImportClauses() { this.mainSourceFile = this.mainSourceFile; const allImportClauses = utils_1.findChildNodes(this.mainSourceFile, ts.isImportDeclaration); for (const tmpImportClause of allImportClauses) { if (tmpImportClause) { if (isNodeCommentTrigger(tmpImportClause, this.mainSourceFile) || this.isImportModuleNameRestrictedGlobally(tmpImportClause)) { logger.trace(`Checking import statement: ${utils_1.nodeToString(tmpImportClause, this.mainSourceFile)}`); this.restrictedExpressions.add(tmpImportClause); if (tmpImportClause.importClause) { if (tmpImportClause.importClause.name) { const importedSymbol = this.tsChecker.getSymbolAtLocation(tmpImportClause.importClause.name); if (importedSymbol) { this.restrictedSymbols.add(importedSymbol); } } if (tmpImportClause.importClause.namedBindings) { if (ts.isNamespaceImport(tmpImportClause.importClause.namedBindings)) { const importedSymbol = this.tsChecker.getSymbolAtLocation(tmpImportClause.importClause.namedBindings.name); if (importedSymbol) { this.restrictedSymbols.add(importedSymbol); } } else if (ts.isNamedImports(tmpImportClause.importClause.namedBindings)) { for (const tmpImportSpecifier of tmpImportClause.importClause .namedBindings.elements) { const importedSymbol = this.tsChecker.getSymbolAtLocation(tmpImportSpecifier.name); if (importedSymbol) { this.restrictedSymbols.add(importedSymbol); } } } } } } } } } findAllRequireStatements() { this.mainSourceFile = this.mainSourceFile; const allRequireCalls = utils_1.findChildNodes(this.mainSourceFile, (node) => ts.isRequireCall(node, true)); for (const tmpRequireCall of allRequireCalls) { const tmpRequireStatement = this.getParentStatement(tmpRequireCall); if (tmpRequireStatement && (isNodeCommentTrigger(tmpRequireStatement, this.mainSourceFile) || this.isRequireModuleNameRestrictedGlobally(tmpRequireCall))) { this.restrictedExpressions.add(tmpRequireCall); } } } findExplicitlyRestrictedSymbols() { const restrictIdentierOrCommaBinaryExpression = (node) => { if (ts.isIdentifier(node)) { const trySymbol = this.tsChecker.getSymbolAtLocation(node); if (trySymbol) { this.restrictedSymbols.add(trySymbol); } } else if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.CommaToken) { restrictIdentierOrCommaBinaryExpression(node.left); restrictIdentierOrCommaBinaryExpression(node.right); } }; const findExpResSymbolsInternal = (node) => { if (ts.isExpressionStatement(node) && isNodeCommentTrigger(node, this.mainSourceFile)) { restrictIdentierOrCommaBinaryExpression(node.expression); } else { ts.forEachChild(node, findExpResSymbolsInternal); } }; ts.forEachChild(this.mainSourceFile, findExpResSymbolsInternal); } isImportModuleNameRestrictedGlobally(importClause) { if (ts.isStringLiteral(importClause.moduleSpecifier)) { const moduleName = importClause.moduleSpecifier.text; return this.options.modules.some(modulePattern => minimatch_1.default(moduleName, modulePattern, this.options.matchOptions)); } return false; } isRequireModuleNameRestrictedGlobally(requireCallExpression) { if (ts.isRequireCall(requireCallExpression, true)) { const moduleName = requireCallExpression .arguments[0].text; return this.options.modules.includes(moduleName); } return false; } isExpressionRestricted(checkeeExpression) { return this.restrictedExpressions.has(checkeeExpression); } isSymbolRestricted(checkeeSymbol) { const isRestrictedSymbol = this.restrictedSymbols.has(checkeeSymbol); const isAliasedRestrictedSymbolOrExpr = this.isSymbolDeclaredWithRestrictedInit(checkeeSymbol) || this.isSymbolAssignedWithRestrictedInit(checkeeSymbol); return isRestrictedSymbol || isAliasedRestrictedSymbolOrExpr; } isSymbolDeclaredWithRestrictedInit(checkeeSymbol) { this.mainSourceFile = this.mainSourceFile; const isDeclarationForGivenSymbol = (node) => { if (ts.isVariableDeclaration(node)) { const variableSymbol = this.tsChecker.getSymbolAtLocation(node.name); const initializer = node.initializer; if (variableSymbol === checkeeSymbol && initializer) { const initializerSymbol = this.tsChecker.getSymbolAtLocation(initializer); if ((initializerSymbol && this.restrictedSymbols.has(initializerSymbol)) || this.restrictedExpressions.has(initializer)) { return true; } } } return false; }; const matchingVarDecl = utils_1.findChildNode(this.mainSourceFile, isDeclarationForGivenSymbol); return matchingVarDecl !== undefined; } isSymbolAssignedWithRestrictedInit(checkeeSymbol) { this.mainSourceFile = this.mainSourceFile; const isVariableAssignmentForGivenSymbol = (node) => { if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.EqualsToken) { const variableSymbol = this.tsChecker.getSymbolAtLocation(node.left); const initializer = node.right; if (variableSymbol === checkeeSymbol && initializer) { const initializerSymbol = this.tsChecker.getSymbolAtLocation(initializer); if ((initializerSymbol && this.restrictedSymbols.has(initializerSymbol)) || this.restrictedExpressions.has(initializer)) { return true; } } } return false; }; const matchingVarAssignment = utils_1.findChildNode(this.mainSourceFile, isVariableAssignmentForGivenSymbol); return matchingVarAssignment !== undefined; } findAllSymbolsAndExpressions() { this.mainSourceFile = this.mainSourceFile; const findAndRecordMethods = [ this.findAndRecordPropertyAccess, this.findAndRecordNewCalls, this.findAndRecordFunctionCalls, ]; let oldRestrictedSymbolsLength = -1; let oldRestrictedExpressionsLength = -1; while (oldRestrictedSymbolsLength < this.restrictedSymbols.size || oldRestrictedExpressionsLength < this.restrictedExpressions.size) { oldRestrictedSymbolsLength = this.restrictedSymbols.size; oldRestrictedExpressionsLength = this.restrictedExpressions.size; findAndRecordMethods.forEach(method => { method.call(this); }); } const expressionsFromSymbols = [...this.restrictedSymbols].flatMap(symbol => this.findExpressionsWhichUseSymbol(symbol)); logger.trace(`Expression from symbols count: ${expressionsFromSymbols.length}`); expressionsFromSymbols.forEach(expr => this.restrictedExpressions.add(expr)); } findAndRecordPropertyAccess() { this.mainSourceFile = this.mainSourceFile; const checkPropAccess = (node) => { if (ts.isPropertyAccessExpression(node)) { const leftHandObjectIdentifier = node.expression; const rightHandPropIdentifier = node.name; const leftHandSymbol = this.tsChecker.getSymbolAtLocation(leftHandObjectIdentifier); const rightHandSymbol = this.tsChecker.getSymbolAtLocation(rightHandPropIdentifier); if ((leftHandSymbol && this.isSymbolRestricted(leftHandSymbol)) || this.isExpressionRestricted(leftHandObjectIdentifier)) { this.restrictedExpressions.add(node); if (leftHandSymbol) { this.restrictedSymbols.add(leftHandSymbol); } } } else { ts.forEachChild(node, checkPropAccess); } }; ts.forEachChild(this.mainSourceFile, checkPropAccess); } findAndRecordNewCalls() { this.mainSourceFile = this.mainSourceFile; const checkSymbolCall = (node) => { if (ts.isNewExpression(node)) { logger.trace('New expression check:', utils_1.nodeToString(node, this.mainSourceFile)); const expressionIdentifier = node.expression; const expressionSymbol = this.tsChecker.getSymbolAtLocation(expressionIdentifier); const newReturnSymbol = this.tsChecker.getSymbolAtLocation(node); if ((expressionSymbol && this.isSymbolRestricted(expressionSymbol)) || this.isExpressionRestricted(expressionIdentifier)) { this.restrictedExpressions.add(node); if (expressionSymbol) { this.restrictedSymbols.add(expressionSymbol); } } } else { ts.forEachChild(node, checkSymbolCall); } }; ts.forEachChild(this.mainSourceFile, checkSymbolCall); } findAndRecordFunctionCalls() { this.mainSourceFile = this.mainSourceFile; const checkFunctionCall = (node) => { if (ts.isCallExpression(node)) { logger.trace('Call expression check:', utils_1.nodeToString(node, this.mainSourceFile)); const expressionIdentifier = node.expression; const expressionSymbol = this.tsChecker.getSymbolAtLocation(expressionIdentifier); const expressionReturnSymbol = this.tsChecker.getSymbolAtLocation(node); if ((expressionSymbol && this.isSymbolRestricted(expressionSymbol)) || this.isExpressionRestricted(expressionIdentifier)) { this.restrictedExpressions.add(node); if (expressionSymbol) { this.restrictedSymbols.add(expressionSymbol); } } } else { ts.forEachChild(node, checkFunctionCall); } }; ts.forEachChild(this.mainSourceFile, checkFunctionCall); } findExpressionsWhichUseSymbol(checkeesymbol, hoistToStatements) { this.mainSourceFile = this.mainSourceFile; if (hoistToStatements === undefined) { hoistToStatements = false; } const matchingExpressions = []; const findExpressionInternal = (node) => { const trySymbol = this.tsChecker.getSymbolAtLocation(node); if (trySymbol && trySymbol === checkeesymbol) { let toPush = node; if (hoistToStatements) { toPush = this.getParentStatement(node); } if (toPush !== undefined) { matchingExpressions.push(node); } } ts.forEachChild(node, findExpressionInternal); }; ts.forEachChild(this.mainSourceFile, findExpressionInternal); return matchingExpressions; } logFindDetails(expressions) { logger.debug('Found symbols: ', [...this.restrictedSymbols] .map(tmpSymbol => tmpSymbol.getName()) .join(', ')); logger.debug('Found expressions: ', expressions .map(expr => utils_1.nodeToString(expr, this.mainSourceFile)) .join(', ')); } getParentStatement(node) { return utils_1.findParentOrSelfNode(node, ts.isStatement); } returntransformedSource() { let newText = this.sourceText; const toRemoveExpressions = [...this.restrictedExpressions] .map((node) => { return this.getParentStatement(node); }) .filter(statementOrUndefined => { return statementOrUndefined !== undefined; }); const revSortedExpressions = toRemoveExpressions.sort((expr1, expr2) => { if (utils_1.getNodeEnd(expr1) !== utils_1.getNodeEnd(expr2)) { if (utils_1.getNodeEnd(expr1) > utils_1.getNodeEnd(expr2)) { return -1; } else { return +1; } } else { if (utils_1.getNodeStart(expr1) < utils_1.getNodeStart(expr2)) { return -1; } else { return +1; } } }); this.logFindDetails(revSortedExpressions); for (let exprIndex = 0; exprIndex < revSortedExpressions.length; exprIndex++) { this.mainSourceFile = this.mainSourceFile; const currentExpr = revSortedExpressions[exprIndex]; if (exprIndex > 0) { const prevExpr = revSortedExpressions[exprIndex - 1]; if (utils_1.getNodeEnd(currentExpr) > utils_1.getNodeStart(prevExpr)) { if (utils_1.getNodeStart(currentExpr) >= utils_1.getNodeStart(prevExpr) && utils_1.getNodeEnd(currentExpr) <= utils_1.getNodeEnd(prevExpr)) { logger.trace(`Skipping expression as it is completely contained: ${utils_1.nodeToString(currentExpr, this.mainSourceFile)}`); continue; } else { throw new Error('Breaking build as there is non-contained overlap between 2 expressions'); } } } const startPosition = utils_1.getNodeStart(currentExpr); let endPosition = utils_1.getNodeEnd(currentExpr); if (newText.slice(endPosition, endPosition + 1) === '\n') { endPosition += 1; } else if (newText.slice(endPosition, endPosition + 2) === '\r\n') { endPosition += 2; } newText = newText.slice(0, startPosition) + '' + newText.slice(endPosition); } return newText; } cleanup() { this.tmpFile.removeCallback(); } } const schema = { type: 'object', properties: { test: { type: 'string', }, }, }; function loader(sourceText) { const options = loader_utils_1.getOptions(this); const newLoaderInstance = new PluginLoader(this, sourceText); return newLoaderInstance.process(); } exports.default = loader; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLWxvYWRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9wbHVnaW4tbG9hZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUFBLDBDQUE0QjtBQUM1Qix1Q0FBeUI7QUFDekIsK0NBQXdEO0FBQ3hELDJDQUE2QjtBQUM3Qix5Q0FBMkI7QUFFM0IsaURBQW1DO0FBQ25DLDBEQUFrQztBQUVsQyxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMseUJBQXlCLENBQUMsQ0FBQztBQUduRCxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7QUFFZixJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLE9BQU8sRUFBRTtJQUNwQyxNQUFNLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7Q0FDN0M7S0FBTSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLE9BQU8sRUFBRTtJQUMzQyxNQUFNLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7Q0FDN0M7S0FBTTtJQUNMLE1BQU0sQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztDQUM3QztBQUVELG1DQVFpQjtBQUVqQixNQUFNLFdBQVcsR0FBRyw0QkFBNEIsQ0FBQztBQUVqRCw4QkFBOEIsSUFBYSxFQUFFLFVBQXlCO0lBQ3BFLE1BQU0sUUFBUSxHQUFHLG1CQUFXLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxXQUFXLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUVuRSxNQUFNLGVBQWUsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1FBQ2pELE9BQU8sV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN0QyxDQUFDLENBQUMsQ0FBQztJQUVILElBQUksZUFBZSxLQUFL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