Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
get parseTree() {
if (!this._parseTree) {
var text = this.text;
// If the source ends with one or more comment, add an empty statement at the end so there's a token
// for the UglifyJS parser to attach them to (workaround for https://github.com/mishoo/UglifyJS2/issues/180)
if (/(?:\/\/[^\r\n]*|\*\/)[\r\s\n]*$/.test(text)) {
text += '\n;';
}
try {
this._parseTree = uglifyJs.parse(text);
} catch (e) {
var err = new errors.ParseError({
message: 'Parse error in ' + this.urlOrDescription + '\n' + e.message + ' (line ' + e.line + ', column ' + (e.col + 1) + ')',
line: e.line,
column: e.col + 1,
asset: this
});
if (this.assetGraph) {
this.assetGraph.emit('warn', err);
} else {
throw err;
}
this._parseTree = uglifyJs.parse('');
}
}
return this._parseTree;
function isNamedDefineNode(node) {
return (
node instanceof uglifyJs.AST_Call &&
node.expression instanceof uglifyJs.AST_Symbol &&
node.expression.name === 'define' &&
node.args.length === 2 &&
node.args[0] instanceof uglifyJs.AST_String
);
}
function shouldCommentNodeBePreservedInNonPrettyPrintedOutput(node, comment) {
return (/@preserve|@license|@cc_on|[@#]\s*sourceURL|[#@]\s*sourceMappingURL|^!/).test(comment.value);
}
// From http://lisperator.net/uglifyjs/transform
var deepCloneTransform = new uglifyJs.TreeTransformer(function (node, descend) {
node = node.clone();
// the descend function expects two arguments:
// the node to dive into, and the tree walker
// `this` here is the tree walker (=== deep_clone).
// by descending into the *cloned* node, we keep the original intact
descend(node, this);
return node;
});
extendWithGettersAndSetters(JavaScript.prototype, {
contentType: 'application/javascript', // TODO: Double check that this is everyone's recommended value
supportedExtensions: ['.js'],
isPretty: false,
if (node instanceof uglifyJs.AST_Constant) {
return node;
} else {
var foldedNode = uglifyAst.foldConstant(node);
if (foldedNode instanceof uglifyJs.AST_String) {
this.markDirty();
return foldedNode;
} else {
return node;
}
}
}.bind(this);
var seenComments = [];
var walker = new uglifyJs.TreeWalker(function (node, descend) {
var stack = walker.stack,
parentNode = walker.parent();
[node.start, node.end].forEach(function (token) {
if (token && token.comments_before) {
token.comments_before.forEach(function (comment) {
var matchSourceUrlOrSourceMappingUrl = comment.value.match(/[@#]\s*source(Mapping)?URL=([^\s\n]*)/);
if (matchSourceUrlOrSourceMappingUrl && seenComments.indexOf(comment) === -1) {
if (matchSourceUrlOrSourceMappingUrl[1] === 'Mapping') {
outgoingRelations.push(new AssetGraph.JavaScriptSourceMappingUrl({
from: this,
node: comment,
to: {
url: matchSourceUrlOrSourceMappingUrl[2],
// Source maps are currently served as application/json, so prevent the target asset
// from being loaded as a Json asset:
type: 'SourceMap'
if (parseTree.end && parseTree.end.comments_before && !parseTree.end._comments_dumped) {
parseTree.end.comments_before.forEach(function (comment) {
if (this.isPretty || shouldCommentNodeBePreservedInNonPrettyPrintedOutput(parseTree.end, comment)) {
if (comment.type === 'comment1') {
text += '//' + comment.value + '\n';
} else if (comment.type === 'comment2') {
text += '/*' + comment.value + '*/';
}
}
}, this);
}
this._text = text;
// Temporary workaround for https://github.com/mishoo/UglifyJS2/issues/218
parseTree.walk(new uglifyJs.TreeWalker(function (node) {
if (node.start) {
node.start._comments_dumped = false;
}
if (node.end) {
node.end._comments_dumped = false;
}
}));
} else {
this._text = this._getTextFromRawSrc();
}
}
return this._text;
},
}
seenComments.push(comment);
}
}, this);
}
}, this);
// Detect global 'use strict' directives
if (parentNode === this.parseTree &&
node instanceof uglifyJs.AST_Directive &&
node.value === 'use strict') {
this.strict = true;
}
if (node instanceof uglifyJs.AST_SimpleStatement &&
node.body instanceof uglifyJs.AST_Call &&
node.body.expression instanceof uglifyJs.AST_Dot &&
node.body.expression.property === 'config' &&
node.body.expression.expression instanceof uglifyJs.AST_SymbolRef &&
node.body.args[0] instanceof uglifyJs.AST_Object &&
(node.body.expression.expression.name === 'require' || node.body.expression.expression.name === 'requirejs')) {
outgoingRelations.push(new AssetGraph.JavaScriptRequireJsConfig({
from: this,
node: node.body.args[0],
parentNode: node.body,
to: new AssetGraph.RequireJsConfig({
parseTree: node.body.args[0].transform(deepCloneTransform)
})
}));
} else if (node instanceof uglifyJs.AST_Var) {
node.definitions.forEach(function (varDefNode) {
url: node.args[0].value
},
node: node,
detachableNode: parentNode instanceof uglifyJs.AST_Seq ? node : parentNode,
parentNode: parentNode instanceof uglifyJs.AST_Seq ? parentNode : parentParentNode
}));
} else {
syntaxErrors.push(new errors.SyntaxError({
message: 'Invalid INCLUDE syntax: Must take a single string argument:' + node.print_to_string(),
asset: this
}));
}
} else if (node.expression instanceof uglifyJs.AST_Symbol && node.expression.name === 'GETTEXT') {
if (node.args.length === 1) {
// TRHTML(GETTEXT(...)) is covered by TRHTML below:
if (!(parentNode instanceof uglifyJs.AST_Call) || !(parentNode.expression instanceof uglifyJs.AST_Symbol) || parentNode.expression.name !== 'TRHTML') {
node.args[0] = tryFoldConstantToString(node.args[0]);
if (node.args[0] instanceof uglifyJs.AST_String) {
outgoingRelations.push(new AssetGraph.JavaScriptGetText({
parentNode: parentNode,
from: this,
to: {
url: node.args[0].value
},
node: node
}));
} else {
syntaxErrors.push(new errors.SyntaxError({
message: 'Invalid GETTEXT syntax: ' + node.print_to_string(),
asset: this
}));
}
from: this,
to: new AssetGraph.Html({
text: keyValue.value.value
}),
node: keyValue,
parentNode: node
}));
}
}, this);
} else if (node instanceof uglifyJs.AST_SimpleStatement) {
if (parentNode instanceof uglifyJs.AST_Function) {
// Use the statements array of the function instead:
parentNode = parentNode.body;
}
if (node.body instanceof uglifyJs.AST_Call &&
node.body.expression instanceof uglifyJs.AST_Dot &&
node.body.expression.property === 'put' &&
node.body.expression.expression instanceof uglifyJs.AST_SymbolRef &&
node.body.expression.expression.name === templateCacheVariableName &&
node.body.args.length === 2 &&
node.body.args[0] instanceof uglifyJs.AST_String &&
node.body.args[1] instanceof uglifyJs.AST_String) {
outgoingRelations.push(new AssetGraph.JavaScriptAngularJsTemplateCacheAssignment({
from: this,
to: new AssetGraph.Html({
isExternalizable: false,
text: node.body.args[1].value
}),
node: node,
parentNode: parentNode
}));
seenComments.push(comment);
}
}, this);
}
}, this);
// Detect global 'use strict' directives
if (parentNode === this.parseTree &&
node instanceof uglifyJs.AST_Directive &&
node.value === 'use strict') {
this.strict = true;
}
if (node instanceof uglifyJs.AST_SimpleStatement &&
node.body instanceof uglifyJs.AST_Call &&
node.body.expression instanceof uglifyJs.AST_Dot &&
node.body.expression.property === 'config' &&
node.body.expression.expression instanceof uglifyJs.AST_SymbolRef &&
node.body.args[0] instanceof uglifyJs.AST_Object &&
(node.body.expression.expression.name === 'require' || node.body.expression.expression.name === 'requirejs')) {
outgoingRelations.push(new AssetGraph.JavaScriptRequireJsConfig({
from: this,
node: node.body.args[0],
parentNode: node.body,
to: new AssetGraph.RequireJsConfig({
parseTree: node.body.args[0].transform(deepCloneTransform)
})
}));
} else if (node instanceof uglifyJs.AST_Var) {
node.definitions.forEach(function (varDefNode) {
if (varDefNode.name.name === 'require' && varDefNode.value instanceof uglifyJs.AST_Object) {
outgoingRelations.push(new AssetGraph.JavaScriptAmdDefine({
from: this,
callNode: node,
arrayNode: arrayNode,
node: arrayItemAst
}));
}
} else {
infos.push(new errors.SyntaxError('Skipping non-string JavaScriptAmdDefine item: ' + node.print_to_string()));
}
}, this);
}
// Keep track of the fact that we're in the body of a define(function () {...}) that might contain
// JavaScriptRequireJsCommonJsCompatibilityRequire relations
var lastArgument = node.args.length > 0 && node.args[node.args.length - 1];
if (lastArgument && lastArgument instanceof uglifyJs.AST_Function) {
nestedDefineNodes.push(node);
descend();
nestedDefineNodes.pop();
return true; // Tell the TreeWalker not to descend again
}
} else if (node.expression instanceof uglifyJs.AST_Symbol && node.expression.name === 'require' &&
node.args.length === 1 && node.args[0] instanceof uglifyJs.AST_String) {
if (nestedDefineNodes.length > 0) {
var parentDefineNode = nestedDefineNodes[nestedDefineNodes.length - 1];
if (!(parentDefineNode.args[0] instanceof uglifyJs.AST_String)) {
outgoingRelations.push(new AssetGraph.JavaScriptRequireJsCommonJsCompatibilityRequire({
parentDefineNode: parentDefineNode,
requireJsConfig: this.assetGraph && this.assetGraph.requireJsConfig, // Hmmm
from: this,
node: node
}));
}
}, this);
// Detect global 'use strict' directives
if (parentNode === this.parseTree &&
node instanceof uglifyJs.AST_Directive &&
node.value === 'use strict') {
this.strict = true;
}
if (node instanceof uglifyJs.AST_SimpleStatement &&
node.body instanceof uglifyJs.AST_Call &&
node.body.expression instanceof uglifyJs.AST_Dot &&
node.body.expression.property === 'config' &&
node.body.expression.expression instanceof uglifyJs.AST_SymbolRef &&
node.body.args[0] instanceof uglifyJs.AST_Object &&
(node.body.expression.expression.name === 'require' || node.body.expression.expression.name === 'requirejs')) {
outgoingRelations.push(new AssetGraph.JavaScriptRequireJsConfig({
from: this,
node: node.body.args[0],
parentNode: node.body,
to: new AssetGraph.RequireJsConfig({
parseTree: node.body.args[0].transform(deepCloneTransform)
})
}));
} else if (node instanceof uglifyJs.AST_Var) {
node.definitions.forEach(function (varDefNode) {
if (varDefNode.name.name === 'require' && varDefNode.value instanceof uglifyJs.AST_Object) {
outgoingRelations.push(new AssetGraph.JavaScriptRequireJsConfig({
isRequireVar: true,
from: this,