ng-annotate
Advanced tools
Comparing version 0.13.0 to 0.14.0
"use strict"; | ||
var os = require("os"); | ||
var convertSourceMap = require("convert-source-map"); | ||
var SourceMapConsumer = require("source-map").SourceMapConsumer; | ||
var SourceMapGenerator = require("source-map").SourceMapGenerator; | ||
var stableSort = require("stable"); | ||
function SourceMapper(src, fragments, inFile, sourceRoot) { | ||
function SourceMapper(src, nodePositions, fragments, inFile, sourceRoot) { | ||
this.generator = new SourceMapGenerator({ sourceRoot: sourceRoot }); | ||
this.src = src; | ||
this.fragments = stableSort(fragments.slice(0), function(a, b) { return a.start - b.start }); | ||
// stableSort does not mutate input array so no need to copy it | ||
this.nodePositions = stableSort(nodePositions, compareLoc); | ||
this.fragments = stableSort(fragments, function(a, b) { return a.start - b.start }); | ||
this.inFile = inFile || "source.js"; | ||
@@ -15,77 +20,102 @@ | ||
SourceMapper.prototype.generate = function() { | ||
var inIndex = 0; | ||
var inLine = 1; | ||
var inColumn = 0; | ||
var outLine = 1; | ||
var outColumn = 0; | ||
var createMappingAfterWhitespace = true; | ||
SourceMapper.prototype.calculateMappings = function() { | ||
var self = this; | ||
while (inIndex < this.src.length) { | ||
if (createMappingAfterWhitespace && !/\s/.test(this.src[inIndex])) { | ||
this.addMapping(inLine, inColumn, outLine, outColumn); | ||
createMappingAfterWhitespace = false; | ||
} | ||
// These offsets represent the difference in coordinates between a node in the source | ||
// and the corresponding position in the output. | ||
var lineOffset = 0; | ||
var columnOffset = 0; | ||
if (this.fragments[0] && this.fragments[0].start === inIndex) { | ||
this.addMapping(inLine, inColumn, outLine, outColumn); | ||
// Since the column position resets to zero after each newline, we have to keep track | ||
// of the current line that columnOffset refers to in order to know whether to reset it | ||
var currentLine = 0; | ||
// iterate over input string | ||
for (; inIndex < this.fragments[0].end; inIndex++) { | ||
if (this.src[inIndex] === '\n') { | ||
inLine++; | ||
inColumn = 0; | ||
} else { | ||
inColumn++; | ||
} | ||
} | ||
var frag = 0; | ||
var pos = 0; | ||
// iterate over output string | ||
for (var outIndex = 0; outIndex < this.fragments[0].str.length; outIndex++) { | ||
if (this.fragments[0].str[outIndex] === '\n') { | ||
outLine++; | ||
outColumn = 0; | ||
} else { | ||
outColumn++; | ||
} | ||
while (pos < self.nodePositions.length) { | ||
while (frag < self.fragments.length && | ||
compareLoc(self.fragments[frag].loc.start, self.nodePositions[pos]) < 1) { | ||
var fragmentLines = self.fragments[frag].str.split("\n"); | ||
var addedNewlines = fragmentLines.length - 1; | ||
var replacedLines = self.fragments[frag].loc.end.line - self.fragments[frag].loc.start.line; | ||
var replacedColumns = self.fragments[frag].loc.end.column - self.fragments[frag].loc.start.column; | ||
// If there were any lines added by the fragment string, the line offset should increase; | ||
// If there were any lines removed by the fragment replacement then the line offset should decrease | ||
lineOffset = lineOffset + addedNewlines - replacedLines; | ||
// The column position needs to reset after each newline. So if the fragment added any | ||
// newlines then the column offset is the difference between the column of the last line of | ||
// the fragment, and the column of the end of the replaced section of the source. | ||
// Otherwise we increment or decrement the column offset just like how the line offset works. | ||
// Note that "replacedColumns" might be negative in some cases (if the beginning of the source | ||
// was further right than the end due to a newline); the math still works out. | ||
columnOffset = fragmentLines.length > 1 ? | ||
fragmentLines[fragmentLines.length - 1].length - self.fragments[frag].loc.end.column : | ||
columnOffset + self.fragments[frag].str.length - replacedColumns; | ||
currentLine = self.fragments[frag].loc.end.line; | ||
// Skip creating mappings for any source nodes that were replaced by this fragment (and are thus | ||
// no longer a part of the output) | ||
while (pos < self.nodePositions.length && | ||
compareLoc(self.fragments[frag].loc.end, self.nodePositions[pos]) > 0) { | ||
++pos; | ||
} | ||
this.fragments.shift(); | ||
createMappingAfterWhitespace = true; | ||
++frag; | ||
} | ||
else { | ||
if (this.src[inIndex] === '\n') { | ||
inLine++; | ||
outLine++; | ||
inColumn = 0; | ||
outColumn = 0; | ||
createMappingAfterWhitespace = true; | ||
} else { | ||
inColumn++; | ||
outColumn++; | ||
} | ||
inIndex++; | ||
if (pos < self.nodePositions.length) { | ||
if (currentLine < self.nodePositions[pos].line) | ||
columnOffset = 0; | ||
self.addMapping(self.nodePositions[pos], { | ||
line: self.nodePositions[pos].line + lineOffset, | ||
column: self.nodePositions[pos].column + columnOffset | ||
}); | ||
++pos; | ||
} | ||
} | ||
return this.generator.toString(); | ||
} | ||
SourceMapper.prototype.addMapping = function(inLine, inColumn, outLine, outColumn) { | ||
SourceMapper.prototype.addMapping = function(input, output) { | ||
this.generator.addMapping({ | ||
source: this.inFile, | ||
original: { | ||
line: inLine, | ||
column: inColumn | ||
}, | ||
generated: { | ||
line: outLine, | ||
column: outColumn | ||
} | ||
original: input, | ||
generated: output | ||
}); | ||
} | ||
module.exports = function generateSourcemap(src, fragments, inFile, sourceRoot) { | ||
return new SourceMapper(src, fragments, inFile, sourceRoot).generate(); | ||
SourceMapper.prototype.applySourceMap = function (consumer) { | ||
this.generator.applySourceMap(consumer); | ||
} | ||
SourceMapper.prototype.generate = function () { | ||
return this.generator.toString(); | ||
} | ||
function compareLoc(a, b) { | ||
return (a.line - b.line) || (a.column - b.column); | ||
} | ||
module.exports = function generateSourcemap(result, src, nodePositions, fragments, mapOpts) { | ||
var existingMap = convertSourceMap.fromSource(src); | ||
src = convertSourceMap.removeMapFileComments(src); | ||
var mapper = new SourceMapper(src, nodePositions, fragments, mapOpts.inFile, mapOpts.sourceRoot); | ||
mapper.calculateMappings(); | ||
if (mapOpts.inline) { | ||
if (existingMap) | ||
mapper.applySourceMap(new SourceMapConsumer(existingMap.toObject())); | ||
result.src = convertSourceMap.removeMapFileComments(result.src) + | ||
os.EOL + | ||
convertSourceMap.fromJSON(mapper.generate()).toComment(); | ||
} else { | ||
result.map = mapper.generate(); | ||
} | ||
} |
@@ -433,25 +433,21 @@ // ng-annotate-main.js | ||
function insertArray(ctx, functionExpression, fragments, quot) { | ||
var range = functionExpression.range; | ||
var args = stringify(ctx, functionExpression.params, quot); | ||
// modify the AST | ||
/* | ||
const arrayExpression = parseExpressionOfType(args, "ArrayExpression"); | ||
const parent = functionExpression.$parent; | ||
replaceNodeWith(functionExpression, arrayExpression); | ||
arrayExpression.$parent = parent; | ||
arrayExpression.elements.push(functionExpression) | ||
functionExpression.$parent = arrayExpression; | ||
*/ | ||
fragments.push({ | ||
start: range[0], | ||
end: range[0], | ||
start: functionExpression.range[0], | ||
end: functionExpression.range[0], | ||
str: args.slice(0, -1) + ", ", | ||
loc: { | ||
start: functionExpression.loc.start, | ||
end: functionExpression.loc.start | ||
} | ||
}); | ||
fragments.push({ | ||
start: range[1], | ||
end: range[1], | ||
start: functionExpression.range[1], | ||
end: functionExpression.range[1], | ||
str: "]", | ||
loc: { | ||
start: functionExpression.loc.end, | ||
end: functionExpression.loc.end | ||
} | ||
}); | ||
@@ -472,2 +468,6 @@ } | ||
str: args.slice(0, -1) + ", ", | ||
loc: { | ||
start: array.loc.start, | ||
end: functionExpression.loc.start | ||
} | ||
}); | ||
@@ -483,2 +483,6 @@ } | ||
str: "", | ||
loc: { | ||
start: array.loc.start, | ||
end: functionExpression.loc.start | ||
} | ||
}); | ||
@@ -489,2 +493,6 @@ fragments.push({ | ||
str: "", | ||
loc: { | ||
start: functionExpression.loc.end, | ||
end: array.loc.end | ||
} | ||
}); | ||
@@ -498,2 +506,11 @@ } | ||
str: renamedString(ctx, literalNode.value), | ||
loc: { | ||
start: { | ||
line: literalNode.loc.start.line, | ||
column: literalNode.loc.start.column + 1 | ||
}, end: { | ||
line: literalNode.loc.end.line, | ||
column: literalNode.loc.end.column - 1 | ||
} | ||
} | ||
}); | ||
@@ -707,4 +724,7 @@ } | ||
var insertPos = onode.range[1]; | ||
var isSemicolonTerminated = (ctx.src[insertPos - 1] === ";"); | ||
var insertPos = { | ||
pos: onode.range[1], | ||
loc: onode.loc.end | ||
}; | ||
var isSemicolonTerminated = (ctx.src[insertPos.pos - 1] === ";"); | ||
@@ -717,3 +737,9 @@ node = jumpOverIife(node); | ||
assert(declaratorName); | ||
addRemoveInjectArray(node.params, isSemicolonTerminated ? insertPos : node.range[1], declaratorName); | ||
addRemoveInjectArray( | ||
node.params, | ||
isSemicolonTerminated ? insertPos : { | ||
pos: node.range[1], | ||
loc: node.loc.end | ||
}, | ||
declaratorName); | ||
@@ -723,3 +749,6 @@ } else if (ctx.isFunctionDeclarationWithArgs(node)) { | ||
addRemoveInjectArray(node.params, insertPos, node.id.name); | ||
addRemoveInjectArray( | ||
node.params, | ||
insertPos, | ||
node.id.name); | ||
@@ -731,3 +760,9 @@ } else if (node.type === "ExpressionStatement" && node.expression.type === "AssignmentExpression" && | ||
var name = ctx.srcForRange(node.expression.left.range); | ||
addRemoveInjectArray(node.expression.right.params, isSemicolonTerminated ? insertPos : node.expression.right.range[1], name); | ||
addRemoveInjectArray( | ||
node.expression.right.params, | ||
isSemicolonTerminated ? insertPos : { | ||
pos: node.expression.right.range[1], | ||
loc: node.expression.right.loc.end | ||
}, | ||
name); | ||
@@ -755,3 +790,3 @@ } else if (node = followReference(node)) { | ||
var indent = getIndent(posAfterFunctionDeclaration); | ||
var indent = getIndent(posAfterFunctionDeclaration.pos); | ||
@@ -783,3 +818,3 @@ var foundSuspectInBody = false; | ||
if (troublesomeReturn && !existingExpressionStatementWithArray) { | ||
posAfterFunctionDeclaration = skipPrevNewline(troublesomeReturn.range[0]); | ||
posAfterFunctionDeclaration = skipPrevNewline(troublesomeReturn.range[0], troublesomeReturn.loc.start); | ||
} | ||
@@ -797,6 +832,6 @@ | ||
function skipPrevNewline(pos) { | ||
function skipPrevNewline(pos, loc) { | ||
var prevLF = ctx.src.lastIndexOf("\n", pos); | ||
if (prevLF === -1) { | ||
return pos; | ||
return { pos: pos, loc: loc }; | ||
} | ||
@@ -808,6 +843,12 @@ if (prevLF >= 1 && ctx.src[prevLF] === "\r") { | ||
if (/\S/g.test(ctx.src.slice(prevLF, pos - 1))) { | ||
return pos; | ||
return { pos: pos, loc: loc }; | ||
} | ||
return prevLF; | ||
return { | ||
pos: prevLF, | ||
loc: { | ||
line: loc.line - 1, | ||
column: prevLF - ctx.src.lastIndexOf("\n", prevLF) | ||
} | ||
}; | ||
} | ||
@@ -822,14 +863,27 @@ | ||
str: str, | ||
loc: { | ||
start: existingExpressionStatementWithArray.loc.start, | ||
end: existingExpressionStatementWithArray.loc.end | ||
} | ||
}); | ||
} else if (ctx.mode === "remove" && existingExpressionStatementWithArray) { | ||
var start = skipPrevNewline(existingExpressionStatementWithArray.range[0], existingExpressionStatementWithArray.loc.start); | ||
ctx.fragments.push({ | ||
start: skipPrevNewline(existingExpressionStatementWithArray.range[0]), | ||
start: start.pos, | ||
end: existingExpressionStatementWithArray.range[1], | ||
str: "", | ||
loc: { | ||
start: start.loc, | ||
end: existingExpressionStatementWithArray.loc.end | ||
} | ||
}); | ||
} else if (is.someof(ctx.mode, ["add", "rebuild"]) && !existingExpressionStatementWithArray) { | ||
ctx.fragments.push({ | ||
start: posAfterFunctionDeclaration, | ||
end: posAfterFunctionDeclaration, | ||
start: posAfterFunctionDeclaration.pos, | ||
end: posAfterFunctionDeclaration.pos, | ||
str: str, | ||
loc: { | ||
start: posAfterFunctionDeclaration.loc, | ||
end: posAfterFunctionDeclaration.loc | ||
} | ||
}); | ||
@@ -918,2 +972,3 @@ } | ||
comment: true, | ||
loc: true, | ||
}); | ||
@@ -949,2 +1004,6 @@ | ||
range: [ast.range[1], ast.range[1]], | ||
loc: { | ||
start: ast.loc.end, | ||
end: ast.loc.end | ||
} | ||
}); | ||
@@ -963,2 +1022,6 @@ | ||
// Position information for all nodes in the AST, | ||
// used for sourcemap generation | ||
var nodePositions = []; | ||
var lut = new Lut(ast, src); | ||
@@ -987,2 +1050,3 @@ | ||
stringify: stringify, | ||
nodePositions: nodePositions, | ||
}; | ||
@@ -1013,2 +1077,3 @@ | ||
}, post: function(node) { | ||
ctx.nodePositions.push(node.loc.start); | ||
var targets = match(node, ctx, matchPluginsOrNull); | ||
@@ -1042,4 +1107,6 @@ if (!targets) { | ||
if (options.sourcemap) { | ||
if (typeof(options.sourcemap) !== 'object') | ||
options.sourcemap = {}; | ||
stats.sourcemap_t0 = Date.now(); | ||
result.map = generateSourcemap(src, fragments, options.inFile, options.sourceroot); | ||
generateSourcemap(result, src, nodePositions, fragments, options.sourcemap); | ||
stats.sourcemap_t1 = Date.now(); | ||
@@ -1046,0 +1113,0 @@ } |
@@ -9,8 +9,6 @@ // ng-annotate.js | ||
var fs = require("fs"); | ||
var os = require("os"); | ||
var fmt = require("simple-fmt"); | ||
var tryor = require("tryor"); | ||
var ngAnnotate = require("./ng-annotate-main"); | ||
var version = "0.13.0"; | ||
var convertSourceMap = require("convert-source-map"); | ||
var version = "0.14.0"; | ||
var optimist = require("optimist") | ||
@@ -111,7 +109,2 @@ .usage("ng-annotate v" + version + "\n\nUsage: ng-annotate OPTIONS <file>\n\n" + | ||
function insertSourcemap(src, map) { | ||
return convertSourceMap.removeMapFileComments(src) + os.EOL + | ||
convertSourceMap.fromJSON(map).toComment(); | ||
} | ||
function runAnnotate(err, src) { | ||
@@ -132,3 +125,3 @@ if (err) { | ||
["add", "remove", "o", "sourcemap", "sourceroot", "regexp", "rename", "single_quotes", "plugin", "stats", "es6"].forEach(function(opt) { | ||
["add", "remove", "o", "regexp", "rename", "single_quotes", "plugin", "stats", "es6"].forEach(function(opt) { | ||
if (opt in argv) { | ||
@@ -139,2 +132,9 @@ config[opt] = argv[opt]; | ||
if (argv.sourcemap) { | ||
config.map = { inline: true, sourceRoot: argv.sourceroot }; | ||
if (filename !== "-") { | ||
config.map.inFile = filename; | ||
} | ||
}; | ||
if (config.plugin) { | ||
@@ -199,9 +199,5 @@ if (!Array.isArray(config.plugin)) { | ||
var output = config.sourcemap ? | ||
insertSourcemap(ret.src, ret.map) : | ||
ret.src; | ||
if (ret.src && config.o) { | ||
try { | ||
fs.writeFileSync(config.o, output); | ||
fs.writeFileSync(config.o, ret.src); | ||
} catch (e) { | ||
@@ -211,4 +207,4 @@ exit(e.message); | ||
} else if (ret.src) { | ||
process.stdout.write(output); | ||
process.stdout.write(ret.src); | ||
} | ||
} |
@@ -9,2 +9,4 @@ // run-tests.js | ||
var fs = require("fs"); | ||
var os = require("os"); | ||
var path = require("path"); | ||
var diff = require("diff"); | ||
@@ -14,2 +16,4 @@ var findLineColumn = require("find-line-column"); | ||
var SourceMapConsumer = require("source-map").SourceMapConsumer; | ||
var coffee = require("coffee-script"); | ||
var convertSourceMap = require("convert-source-map"); | ||
@@ -20,2 +24,9 @@ function slurp(filename) { | ||
function time(str, fn) { | ||
var t0 = Date.now(); | ||
fn(); | ||
var t1 = Date.now(); | ||
console.log(fmt(str, t1 - t0)); | ||
} | ||
function test(correct, got, name) { | ||
@@ -44,6 +55,26 @@ if (got !== correct) { | ||
function stringRegExp(commentText) { | ||
return new RegExp("\"" + commentText + "\""); | ||
} | ||
function functionRegExp(functionName) { | ||
return new RegExp("(function)?\\(" + functionName + "_param1, " + functionName + "_param2\\)") | ||
} | ||
function testMapping(needle) { | ||
var gotPosition = findLineColumn(got, needle.exec(got).index); | ||
var gotResult = needle.exec(got); | ||
if (gotResult == null) { | ||
process.stderr.write(fmt("Couldn't find {0} in output source", needle)); | ||
process.exit(-1); | ||
} | ||
var expectedResult = needle.exec(original); | ||
if (expectedResult == null) { | ||
process.stderr.write(fmt("Couldn't find {0} in expected source", needle)); | ||
process.exit(-1); | ||
} | ||
var gotPosition = findLineColumn(got, gotResult.index); | ||
var originalPosition = smc.originalPositionFor({ line: gotPosition.line, column: gotPosition.col }); | ||
var expectedPosition = findLineColumn(original, needle.exec(original).index); | ||
var expectedPosition = findLineColumn(original, expectedResult.index); | ||
@@ -60,8 +91,8 @@ if (originalPosition.line !== expectedPosition.line || originalPosition.column !== expectedPosition.col) { | ||
testMapping(/\/\* before \*\//); | ||
testMapping(stringRegExp("before")); | ||
for (var i = 1; i <= 4; i++) { | ||
testMapping(new RegExp("function( ctrl" + i + ")?\\(ctrl" + i + "_param1")); | ||
testMapping(new RegExp("/\\* ctrl" + i + " body \\*/")); | ||
testMapping(functionRegExp("ctrl" + i)); | ||
testMapping(stringRegExp("ctrl" + i + " body")); | ||
} | ||
testMapping(/\/\* after \*\//); | ||
testMapping(stringRegExp("after")); | ||
} | ||
@@ -99,7 +130,17 @@ | ||
console.log("testing sourcemaps"); | ||
var originalSourcemaps = slurp("tests/sourcemaps.js"); | ||
var annotatedSourcemaps = ngAnnotate(originalSourcemaps, {remove: true, add: true, sourcemap: true, sourceroot: "/source/root/dir"}); | ||
var originalSourcemaps = slurp("tests/sourcemaps.coffee"); | ||
var compiledSourcemaps = coffee.compile(originalSourcemaps, { sourceFiles: ["sourcemaps.coffee"], generatedFile: "sourcemaps.js", sourceMap: true }); | ||
var annotatedSourcemaps = ngAnnotate(compiledSourcemaps.js, {remove: true, add: true, sourcemap: { sourceRoot: "/source/root/dir" }}); | ||
test(slurp("tests/sourcemaps.annotated.js"), annotatedSourcemaps.src, "sourcemaps.annotated.js"); | ||
testSourcemap(originalSourcemaps, annotatedSourcemaps.src, annotatedSourcemaps.map, "sourcemaps.annotated.js.map"); | ||
testSourcemap(compiledSourcemaps.js, annotatedSourcemaps.src, annotatedSourcemaps.map, "sourcemaps.annotated.js.map"); | ||
console.log("testing sourcemap combination"); | ||
var inlinedCompiledSourcemaps = compiledSourcemaps.js + | ||
os.EOL + | ||
convertSourceMap.fromJSON(compiledSourcemaps.v3SourceMap).toComment(); | ||
var combinedSourcemaps = ngAnnotate(inlinedCompiledSourcemaps, {remove: true, add: true, sourcemap: { inline: true, inFile: "sourcemaps.js", sourceRoot: "/source/root/dir" }}); | ||
var combinedSourcemapsSrc = convertSourceMap.removeMapFileComments(combinedSourcemaps.src); | ||
var combinedSourcemapsMap = convertSourceMap.fromSource(combinedSourcemaps.src).toJSON(); | ||
testSourcemap(originalSourcemaps, combinedSourcemapsSrc, combinedSourcemapsMap, "sourcemaps.annotated.js.map"); | ||
var ngminOriginal = slurp("tests/ngmin-tests/ngmin_original.js"); | ||
@@ -133,2 +174,13 @@ | ||
if (fs.existsSync("tests/angular.js")) { | ||
console.log("testing performance"); | ||
var ng1 = String(fs.readFileSync("tests/angular.js")); | ||
var ng5 = ng1 + ng1 + ng1 + ng1 + ng1; | ||
time(" ng1 processed in {0} ms", function() { ngAnnotate(ng1, {add: true}) }); | ||
time(" ng1 processed with sourcemaps in {0} ms", function() { ngAnnotate(ng1, {add: true, sourcemap: true}) }); | ||
//time(" ng5 processed in {0} ms", function() { ngAnnotate(ng5, {add: true}) }); | ||
//time(" ng5 processed with sourcemaps in {0} ms", function() { ngAnnotate(ng5, {add: true, sourcemap: true}) }); | ||
} | ||
console.log("all ok"); | ||
@@ -135,0 +187,0 @@ } |
@@ -1,24 +0,30 @@ | ||
(function () { | ||
(function() { | ||
var ctrl4, x; | ||
/* before */ | ||
x = "before"; | ||
myMod.controller("ctrl1", ["ctrl1_param1", "ctrl1_param2", function(ctrl1_param1, ctrl1_param2) { | ||
/* ctrl1 body */ | ||
}]); | ||
myMod.controller("ctrl2", ["ctrl2_param1", "ctrl2_param2", function(ctrl2_param1, ctrl2_param2) { | ||
/* ctrl2 body */ | ||
}]); | ||
myMod.controller("ctrl3", ["ctrl3_param1", "ctrl3_param2", function(ctrl3_param1, ctrl3_param2) { | ||
/* ctrl3 body */ | ||
} | ||
]); | ||
myMod.controller("ctrl1", ["ctrl1_param1", "ctrl1_param2", function(ctrl1_param1, ctrl1_param2) { | ||
return x = "ctrl1 body"; | ||
}]); | ||
/*@ngInject*/ | ||
function ctrl4(ctrl4_param1, ctrl4_param2) { | ||
/* ctrl4 body */ | ||
myMod.controller("ctrl2", ["ctrl2_param1", "ctrl2_param2", function(ctrl2_param1, ctrl2_param2) { | ||
return x = "ctrl2 body"; | ||
} | ||
ctrl4.$inject = ["ctrl4_param1", "ctrl4_param2"]; | ||
]); | ||
/* after */ | ||
myMod.controller("ctrl3", ["ctrl3_param1", "ctrl3_param2", function(ctrl3_param1, ctrl3_param2) { | ||
return x = "ctrl3 body"; | ||
} | ||
]); | ||
})(); | ||
/* @ngInject */ | ||
ctrl4 = function(ctrl4_param1, ctrl4_param2) { | ||
return x = "ctrl4 body"; | ||
}; | ||
ctrl4.$inject = ["ctrl4_param1", "ctrl4_param2"]; | ||
x = "after"; | ||
}).call(this); |
@@ -0,1 +1,4 @@ | ||
## v0.14.0 2014-11-27 | ||
* support sourcemap combination and better map granularity | ||
## v0.13.0 2014-11-18 | ||
@@ -2,0 +5,0 @@ * match $mdDialog.show, $mdToast.show and $mdBottomSheet.show |
"use strict"; | ||
const os = require("os"); | ||
const convertSourceMap = require("convert-source-map"); | ||
const SourceMapConsumer = require("source-map").SourceMapConsumer; | ||
const SourceMapGenerator = require("source-map").SourceMapGenerator; | ||
const stableSort = require("stable"); | ||
function SourceMapper(src, fragments, inFile, sourceRoot) { | ||
function SourceMapper(src, nodePositions, fragments, inFile, sourceRoot) { | ||
this.generator = new SourceMapGenerator({ sourceRoot: sourceRoot }); | ||
this.src = src; | ||
this.fragments = stableSort(fragments.slice(0), function(a, b) { return a.start - b.start }); | ||
// stableSort does not mutate input array so no need to copy it | ||
this.nodePositions = stableSort(nodePositions, compareLoc); | ||
this.fragments = stableSort(fragments, function(a, b) { return a.start - b.start }); | ||
this.inFile = inFile || "source.js"; | ||
@@ -15,77 +20,102 @@ | ||
SourceMapper.prototype.generate = function() { | ||
let inIndex = 0; | ||
let inLine = 1; | ||
let inColumn = 0; | ||
let outLine = 1; | ||
let outColumn = 0; | ||
let createMappingAfterWhitespace = true; | ||
SourceMapper.prototype.calculateMappings = function() { | ||
const self = this; | ||
while (inIndex < this.src.length) { | ||
if (createMappingAfterWhitespace && !/\s/.test(this.src[inIndex])) { | ||
this.addMapping(inLine, inColumn, outLine, outColumn); | ||
createMappingAfterWhitespace = false; | ||
} | ||
// These offsets represent the difference in coordinates between a node in the source | ||
// and the corresponding position in the output. | ||
let lineOffset = 0; | ||
let columnOffset = 0; | ||
if (this.fragments[0] && this.fragments[0].start === inIndex) { | ||
this.addMapping(inLine, inColumn, outLine, outColumn); | ||
// Since the column position resets to zero after each newline, we have to keep track | ||
// of the current line that columnOffset refers to in order to know whether to reset it | ||
let currentLine = 0; | ||
// iterate over input string | ||
for (; inIndex < this.fragments[0].end; inIndex++) { | ||
if (this.src[inIndex] === '\n') { | ||
inLine++; | ||
inColumn = 0; | ||
} else { | ||
inColumn++; | ||
} | ||
} | ||
let frag = 0; | ||
let pos = 0; | ||
// iterate over output string | ||
for (let outIndex = 0; outIndex < this.fragments[0].str.length; outIndex++) { | ||
if (this.fragments[0].str[outIndex] === '\n') { | ||
outLine++; | ||
outColumn = 0; | ||
} else { | ||
outColumn++; | ||
} | ||
while (pos < self.nodePositions.length) { | ||
while (frag < self.fragments.length && | ||
compareLoc(self.fragments[frag].loc.start, self.nodePositions[pos]) < 1) { | ||
const fragmentLines = self.fragments[frag].str.split("\n"); | ||
const addedNewlines = fragmentLines.length - 1; | ||
const replacedLines = self.fragments[frag].loc.end.line - self.fragments[frag].loc.start.line; | ||
const replacedColumns = self.fragments[frag].loc.end.column - self.fragments[frag].loc.start.column; | ||
// If there were any lines added by the fragment string, the line offset should increase; | ||
// If there were any lines removed by the fragment replacement then the line offset should decrease | ||
lineOffset = lineOffset + addedNewlines - replacedLines; | ||
// The column position needs to reset after each newline. So if the fragment added any | ||
// newlines then the column offset is the difference between the column of the last line of | ||
// the fragment, and the column of the end of the replaced section of the source. | ||
// Otherwise we increment or decrement the column offset just like how the line offset works. | ||
// Note that "replacedColumns" might be negative in some cases (if the beginning of the source | ||
// was further right than the end due to a newline); the math still works out. | ||
columnOffset = fragmentLines.length > 1 ? | ||
fragmentLines[fragmentLines.length - 1].length - self.fragments[frag].loc.end.column : | ||
columnOffset + self.fragments[frag].str.length - replacedColumns; | ||
currentLine = self.fragments[frag].loc.end.line; | ||
// Skip creating mappings for any source nodes that were replaced by this fragment (and are thus | ||
// no longer a part of the output) | ||
while (pos < self.nodePositions.length && | ||
compareLoc(self.fragments[frag].loc.end, self.nodePositions[pos]) > 0) { | ||
++pos; | ||
} | ||
this.fragments.shift(); | ||
createMappingAfterWhitespace = true; | ||
++frag; | ||
} | ||
else { | ||
if (this.src[inIndex] === '\n') { | ||
inLine++; | ||
outLine++; | ||
inColumn = 0; | ||
outColumn = 0; | ||
createMappingAfterWhitespace = true; | ||
} else { | ||
inColumn++; | ||
outColumn++; | ||
} | ||
inIndex++; | ||
if (pos < self.nodePositions.length) { | ||
if (currentLine < self.nodePositions[pos].line) | ||
columnOffset = 0; | ||
self.addMapping(self.nodePositions[pos], { | ||
line: self.nodePositions[pos].line + lineOffset, | ||
column: self.nodePositions[pos].column + columnOffset | ||
}); | ||
++pos; | ||
} | ||
} | ||
return this.generator.toString(); | ||
} | ||
SourceMapper.prototype.addMapping = function(inLine, inColumn, outLine, outColumn) { | ||
SourceMapper.prototype.addMapping = function(input, output) { | ||
this.generator.addMapping({ | ||
source: this.inFile, | ||
original: { | ||
line: inLine, | ||
column: inColumn | ||
}, | ||
generated: { | ||
line: outLine, | ||
column: outColumn | ||
} | ||
original: input, | ||
generated: output | ||
}); | ||
} | ||
module.exports = function generateSourcemap(src, fragments, inFile, sourceRoot) { | ||
return new SourceMapper(src, fragments, inFile, sourceRoot).generate(); | ||
SourceMapper.prototype.applySourceMap = function (consumer) { | ||
this.generator.applySourceMap(consumer); | ||
} | ||
SourceMapper.prototype.generate = function () { | ||
return this.generator.toString(); | ||
} | ||
function compareLoc(a, b) { | ||
return (a.line - b.line) || (a.column - b.column); | ||
} | ||
module.exports = function generateSourcemap(result, src, nodePositions, fragments, mapOpts) { | ||
const existingMap = convertSourceMap.fromSource(src); | ||
src = convertSourceMap.removeMapFileComments(src); | ||
const mapper = new SourceMapper(src, nodePositions, fragments, mapOpts.inFile, mapOpts.sourceRoot); | ||
mapper.calculateMappings(); | ||
if (mapOpts.inline) { | ||
if (existingMap) | ||
mapper.applySourceMap(new SourceMapConsumer(existingMap.toObject())); | ||
result.src = convertSourceMap.removeMapFileComments(result.src) + | ||
os.EOL + | ||
convertSourceMap.fromJSON(mapper.generate()).toComment(); | ||
} else { | ||
result.map = mapper.generate(); | ||
} | ||
} |
@@ -433,25 +433,21 @@ // ng-annotate-main.js | ||
function insertArray(ctx, functionExpression, fragments, quot) { | ||
const range = functionExpression.range; | ||
const args = stringify(ctx, functionExpression.params, quot); | ||
// modify the AST | ||
/* | ||
const arrayExpression = parseExpressionOfType(args, "ArrayExpression"); | ||
const parent = functionExpression.$parent; | ||
replaceNodeWith(functionExpression, arrayExpression); | ||
arrayExpression.$parent = parent; | ||
arrayExpression.elements.push(functionExpression) | ||
functionExpression.$parent = arrayExpression; | ||
*/ | ||
fragments.push({ | ||
start: range[0], | ||
end: range[0], | ||
start: functionExpression.range[0], | ||
end: functionExpression.range[0], | ||
str: args.slice(0, -1) + ", ", | ||
loc: { | ||
start: functionExpression.loc.start, | ||
end: functionExpression.loc.start | ||
} | ||
}); | ||
fragments.push({ | ||
start: range[1], | ||
end: range[1], | ||
start: functionExpression.range[1], | ||
end: functionExpression.range[1], | ||
str: "]", | ||
loc: { | ||
start: functionExpression.loc.end, | ||
end: functionExpression.loc.end | ||
} | ||
}); | ||
@@ -472,2 +468,6 @@ } | ||
str: args.slice(0, -1) + ", ", | ||
loc: { | ||
start: array.loc.start, | ||
end: functionExpression.loc.start | ||
} | ||
}); | ||
@@ -483,2 +483,6 @@ } | ||
str: "", | ||
loc: { | ||
start: array.loc.start, | ||
end: functionExpression.loc.start | ||
} | ||
}); | ||
@@ -489,2 +493,6 @@ fragments.push({ | ||
str: "", | ||
loc: { | ||
start: functionExpression.loc.end, | ||
end: array.loc.end | ||
} | ||
}); | ||
@@ -498,2 +506,11 @@ } | ||
str: renamedString(ctx, literalNode.value), | ||
loc: { | ||
start: { | ||
line: literalNode.loc.start.line, | ||
column: literalNode.loc.start.column + 1 | ||
}, end: { | ||
line: literalNode.loc.end.line, | ||
column: literalNode.loc.end.column - 1 | ||
} | ||
} | ||
}); | ||
@@ -707,4 +724,7 @@ } | ||
const insertPos = onode.range[1]; | ||
const isSemicolonTerminated = (ctx.src[insertPos - 1] === ";"); | ||
const insertPos = { | ||
pos: onode.range[1], | ||
loc: onode.loc.end | ||
}; | ||
const isSemicolonTerminated = (ctx.src[insertPos.pos - 1] === ";"); | ||
@@ -717,3 +737,9 @@ node = jumpOverIife(node); | ||
assert(declaratorName); | ||
addRemoveInjectArray(node.params, isSemicolonTerminated ? insertPos : node.range[1], declaratorName); | ||
addRemoveInjectArray( | ||
node.params, | ||
isSemicolonTerminated ? insertPos : { | ||
pos: node.range[1], | ||
loc: node.loc.end | ||
}, | ||
declaratorName); | ||
@@ -723,3 +749,6 @@ } else if (ctx.isFunctionDeclarationWithArgs(node)) { | ||
addRemoveInjectArray(node.params, insertPos, node.id.name); | ||
addRemoveInjectArray( | ||
node.params, | ||
insertPos, | ||
node.id.name); | ||
@@ -731,3 +760,9 @@ } else if (node.type === "ExpressionStatement" && node.expression.type === "AssignmentExpression" && | ||
const name = ctx.srcForRange(node.expression.left.range); | ||
addRemoveInjectArray(node.expression.right.params, isSemicolonTerminated ? insertPos : node.expression.right.range[1], name); | ||
addRemoveInjectArray( | ||
node.expression.right.params, | ||
isSemicolonTerminated ? insertPos : { | ||
pos: node.expression.right.range[1], | ||
loc: node.expression.right.loc.end | ||
}, | ||
name); | ||
@@ -755,3 +790,3 @@ } else if (node = followReference(node)) { | ||
const indent = getIndent(posAfterFunctionDeclaration); | ||
const indent = getIndent(posAfterFunctionDeclaration.pos); | ||
@@ -783,3 +818,3 @@ let foundSuspectInBody = false; | ||
if (troublesomeReturn && !existingExpressionStatementWithArray) { | ||
posAfterFunctionDeclaration = skipPrevNewline(troublesomeReturn.range[0]); | ||
posAfterFunctionDeclaration = skipPrevNewline(troublesomeReturn.range[0], troublesomeReturn.loc.start); | ||
} | ||
@@ -797,6 +832,6 @@ | ||
function skipPrevNewline(pos) { | ||
function skipPrevNewline(pos, loc) { | ||
let prevLF = ctx.src.lastIndexOf("\n", pos); | ||
if (prevLF === -1) { | ||
return pos; | ||
return { pos: pos, loc: loc }; | ||
} | ||
@@ -808,6 +843,12 @@ if (prevLF >= 1 && ctx.src[prevLF] === "\r") { | ||
if (/\S/g.test(ctx.src.slice(prevLF, pos - 1))) { | ||
return pos; | ||
return { pos: pos, loc: loc }; | ||
} | ||
return prevLF; | ||
return { | ||
pos: prevLF, | ||
loc: { | ||
line: loc.line - 1, | ||
column: prevLF - ctx.src.lastIndexOf("\n", prevLF) | ||
} | ||
}; | ||
} | ||
@@ -822,14 +863,27 @@ | ||
str: str, | ||
loc: { | ||
start: existingExpressionStatementWithArray.loc.start, | ||
end: existingExpressionStatementWithArray.loc.end | ||
} | ||
}); | ||
} else if (ctx.mode === "remove" && existingExpressionStatementWithArray) { | ||
const start = skipPrevNewline(existingExpressionStatementWithArray.range[0], existingExpressionStatementWithArray.loc.start); | ||
ctx.fragments.push({ | ||
start: skipPrevNewline(existingExpressionStatementWithArray.range[0]), | ||
start: start.pos, | ||
end: existingExpressionStatementWithArray.range[1], | ||
str: "", | ||
loc: { | ||
start: start.loc, | ||
end: existingExpressionStatementWithArray.loc.end | ||
} | ||
}); | ||
} else if (is.someof(ctx.mode, ["add", "rebuild"]) && !existingExpressionStatementWithArray) { | ||
ctx.fragments.push({ | ||
start: posAfterFunctionDeclaration, | ||
end: posAfterFunctionDeclaration, | ||
start: posAfterFunctionDeclaration.pos, | ||
end: posAfterFunctionDeclaration.pos, | ||
str: str, | ||
loc: { | ||
start: posAfterFunctionDeclaration.loc, | ||
end: posAfterFunctionDeclaration.loc | ||
} | ||
}); | ||
@@ -918,2 +972,3 @@ } | ||
comment: true, | ||
loc: true, | ||
}); | ||
@@ -949,2 +1004,6 @@ | ||
range: [ast.range[1], ast.range[1]], | ||
loc: { | ||
start: ast.loc.end, | ||
end: ast.loc.end | ||
} | ||
}); | ||
@@ -963,2 +1022,6 @@ | ||
// Position information for all nodes in the AST, | ||
// used for sourcemap generation | ||
const nodePositions = []; | ||
const lut = new Lut(ast, src); | ||
@@ -987,2 +1050,3 @@ | ||
stringify: stringify, | ||
nodePositions: nodePositions, | ||
}; | ||
@@ -1013,2 +1077,3 @@ | ||
}, post: function(node) { | ||
ctx.nodePositions.push(node.loc.start); | ||
let targets = match(node, ctx, matchPluginsOrNull); | ||
@@ -1042,4 +1107,6 @@ if (!targets) { | ||
if (options.sourcemap) { | ||
if (typeof(options.sourcemap) !== 'object') | ||
options.sourcemap = {}; | ||
stats.sourcemap_t0 = Date.now(); | ||
result.map = generateSourcemap(src, fragments, options.inFile, options.sourceroot); | ||
generateSourcemap(result, src, nodePositions, fragments, options.sourcemap); | ||
stats.sourcemap_t1 = Date.now(); | ||
@@ -1046,0 +1113,0 @@ } |
@@ -9,3 +9,2 @@ // ng-annotate.js | ||
const fs = require("fs"); | ||
const os = require("os"); | ||
const fmt = require("simple-fmt"); | ||
@@ -15,3 +14,2 @@ const tryor = require("tryor"); | ||
const version = require("./package.json").version; | ||
const convertSourceMap = require("convert-source-map"); | ||
const optimist = require("optimist") | ||
@@ -112,7 +110,2 @@ .usage("ng-annotate v" + version + "\n\nUsage: ng-annotate OPTIONS <file>\n\n" + | ||
function insertSourcemap(src, map) { | ||
return convertSourceMap.removeMapFileComments(src) + os.EOL + | ||
convertSourceMap.fromJSON(map).toComment(); | ||
} | ||
function runAnnotate(err, src) { | ||
@@ -133,3 +126,3 @@ if (err) { | ||
["add", "remove", "o", "sourcemap", "sourceroot", "regexp", "rename", "single_quotes", "plugin", "stats", "es6"].forEach(function(opt) { | ||
["add", "remove", "o", "regexp", "rename", "single_quotes", "plugin", "stats", "es6"].forEach(function(opt) { | ||
if (opt in argv) { | ||
@@ -140,2 +133,9 @@ config[opt] = argv[opt]; | ||
if (argv.sourcemap) { | ||
config.map = { inline: true, sourceRoot: argv.sourceroot }; | ||
if (filename !== "-") { | ||
config.map.inFile = filename; | ||
} | ||
}; | ||
if (config.plugin) { | ||
@@ -200,9 +200,5 @@ if (!Array.isArray(config.plugin)) { | ||
const output = config.sourcemap ? | ||
insertSourcemap(ret.src, ret.map) : | ||
ret.src; | ||
if (ret.src && config.o) { | ||
try { | ||
fs.writeFileSync(config.o, output); | ||
fs.writeFileSync(config.o, ret.src); | ||
} catch (e) { | ||
@@ -212,4 +208,4 @@ exit(e.message); | ||
} else if (ret.src) { | ||
process.stdout.write(output); | ||
process.stdout.write(ret.src); | ||
} | ||
} |
{ | ||
"name": "ng-annotate", | ||
"version": "0.13.0", | ||
"version": "0.14.0", | ||
"description": "add, remove and rebuild angularjs dependency injection annotations", | ||
@@ -26,2 +26,3 @@ "main": "build/es5/ng-annotate-main.js", | ||
"devDependencies": { | ||
"coffee-script": "~1.8.0", | ||
"defs": "~0.6.2", | ||
@@ -28,0 +29,0 @@ "diff": "~1.0.8", |
@@ -319,4 +319,3 @@ # ng-annotate | ||
rename: [{from: "generalname", to: "uniquename"}, {from: "alpha", to: "beta"}], | ||
sourcemap: true, | ||
sourceroot: "/path/to/source/root", | ||
sourcemap: { inline: false, inFile: "source.js", sourceRoot: "/path/to/source/root" } | ||
}); | ||
@@ -323,0 +322,0 @@ var errorstringArray = res.errors; |
@@ -9,2 +9,4 @@ // run-tests.js | ||
const fs = require("fs"); | ||
const os = require("os"); | ||
const path = require("path"); | ||
const diff = require("diff"); | ||
@@ -14,2 +16,4 @@ const findLineColumn = require("find-line-column"); | ||
const SourceMapConsumer = require("source-map").SourceMapConsumer; | ||
const coffee = require("coffee-script"); | ||
const convertSourceMap = require("convert-source-map"); | ||
@@ -20,2 +24,9 @@ function slurp(filename) { | ||
function time(str, fn) { | ||
const t0 = Date.now(); | ||
fn(); | ||
const t1 = Date.now(); | ||
console.log(fmt(str, t1 - t0)); | ||
} | ||
function test(correct, got, name) { | ||
@@ -44,6 +55,26 @@ if (got !== correct) { | ||
function stringRegExp(commentText) { | ||
return new RegExp("\"" + commentText + "\""); | ||
} | ||
function functionRegExp(functionName) { | ||
return new RegExp("(function)?\\(" + functionName + "_param1, " + functionName + "_param2\\)") | ||
} | ||
function testMapping(needle) { | ||
const gotPosition = findLineColumn(got, needle.exec(got).index); | ||
const gotResult = needle.exec(got); | ||
if (gotResult == null) { | ||
process.stderr.write(fmt("Couldn't find {0} in output source", needle)); | ||
process.exit(-1); | ||
} | ||
const expectedResult = needle.exec(original); | ||
if (expectedResult == null) { | ||
process.stderr.write(fmt("Couldn't find {0} in expected source", needle)); | ||
process.exit(-1); | ||
} | ||
const gotPosition = findLineColumn(got, gotResult.index); | ||
const originalPosition = smc.originalPositionFor({ line: gotPosition.line, column: gotPosition.col }); | ||
const expectedPosition = findLineColumn(original, needle.exec(original).index); | ||
const expectedPosition = findLineColumn(original, expectedResult.index); | ||
@@ -60,8 +91,8 @@ if (originalPosition.line !== expectedPosition.line || originalPosition.column !== expectedPosition.col) { | ||
testMapping(/\/\* before \*\//); | ||
testMapping(stringRegExp("before")); | ||
for (let i = 1; i <= 4; i++) { | ||
testMapping(new RegExp("function( ctrl" + i + ")?\\(ctrl" + i + "_param1")); | ||
testMapping(new RegExp("/\\* ctrl" + i + " body \\*/")); | ||
testMapping(functionRegExp("ctrl" + i)); | ||
testMapping(stringRegExp("ctrl" + i + " body")); | ||
} | ||
testMapping(/\/\* after \*\//); | ||
testMapping(stringRegExp("after")); | ||
} | ||
@@ -99,7 +130,17 @@ | ||
console.log("testing sourcemaps"); | ||
const originalSourcemaps = slurp("tests/sourcemaps.js"); | ||
const annotatedSourcemaps = ngAnnotate(originalSourcemaps, {remove: true, add: true, sourcemap: true, sourceroot: "/source/root/dir"}); | ||
const originalSourcemaps = slurp("tests/sourcemaps.coffee"); | ||
const compiledSourcemaps = coffee.compile(originalSourcemaps, { sourceFiles: ["sourcemaps.coffee"], generatedFile: "sourcemaps.js", sourceMap: true }); | ||
const annotatedSourcemaps = ngAnnotate(compiledSourcemaps.js, {remove: true, add: true, sourcemap: { sourceRoot: "/source/root/dir" }}); | ||
test(slurp("tests/sourcemaps.annotated.js"), annotatedSourcemaps.src, "sourcemaps.annotated.js"); | ||
testSourcemap(originalSourcemaps, annotatedSourcemaps.src, annotatedSourcemaps.map, "sourcemaps.annotated.js.map"); | ||
testSourcemap(compiledSourcemaps.js, annotatedSourcemaps.src, annotatedSourcemaps.map, "sourcemaps.annotated.js.map"); | ||
console.log("testing sourcemap combination"); | ||
const inlinedCompiledSourcemaps = compiledSourcemaps.js + | ||
os.EOL + | ||
convertSourceMap.fromJSON(compiledSourcemaps.v3SourceMap).toComment(); | ||
const combinedSourcemaps = ngAnnotate(inlinedCompiledSourcemaps, {remove: true, add: true, sourcemap: { inline: true, inFile: "sourcemaps.js", sourceRoot: "/source/root/dir" }}); | ||
const combinedSourcemapsSrc = convertSourceMap.removeMapFileComments(combinedSourcemaps.src); | ||
const combinedSourcemapsMap = convertSourceMap.fromSource(combinedSourcemaps.src).toJSON(); | ||
testSourcemap(originalSourcemaps, combinedSourcemapsSrc, combinedSourcemapsMap, "sourcemaps.annotated.js.map"); | ||
const ngminOriginal = slurp("tests/ngmin-tests/ngmin_original.js"); | ||
@@ -133,2 +174,13 @@ | ||
if (fs.existsSync("tests/angular.js")) { | ||
console.log("testing performance"); | ||
const ng1 = String(fs.readFileSync("tests/angular.js")); | ||
const ng5 = ng1 + ng1 + ng1 + ng1 + ng1; | ||
time(" ng1 processed in {0} ms", function() { ngAnnotate(ng1, {add: true}) }); | ||
time(" ng1 processed with sourcemaps in {0} ms", function() { ngAnnotate(ng1, {add: true, sourcemap: true}) }); | ||
//time(" ng5 processed in {0} ms", function() { ngAnnotate(ng5, {add: true}) }); | ||
//time(" ng5 processed with sourcemaps in {0} ms", function() { ngAnnotate(ng5, {add: true, sourcemap: true}) }); | ||
} | ||
console.log("all ok"); | ||
@@ -135,0 +187,0 @@ } |
@@ -1,24 +0,30 @@ | ||
(function () { | ||
(function() { | ||
var ctrl4, x; | ||
/* before */ | ||
x = "before"; | ||
myMod.controller("ctrl1", ["ctrl1_param1", "ctrl1_param2", function(ctrl1_param1, ctrl1_param2) { | ||
/* ctrl1 body */ | ||
}]); | ||
myMod.controller("ctrl2", ["ctrl2_param1", "ctrl2_param2", function(ctrl2_param1, ctrl2_param2) { | ||
/* ctrl2 body */ | ||
}]); | ||
myMod.controller("ctrl3", ["ctrl3_param1", "ctrl3_param2", function(ctrl3_param1, ctrl3_param2) { | ||
/* ctrl3 body */ | ||
} | ||
]); | ||
myMod.controller("ctrl1", ["ctrl1_param1", "ctrl1_param2", function(ctrl1_param1, ctrl1_param2) { | ||
return x = "ctrl1 body"; | ||
}]); | ||
/*@ngInject*/ | ||
function ctrl4(ctrl4_param1, ctrl4_param2) { | ||
/* ctrl4 body */ | ||
myMod.controller("ctrl2", ["ctrl2_param1", "ctrl2_param2", function(ctrl2_param1, ctrl2_param2) { | ||
return x = "ctrl2 body"; | ||
} | ||
ctrl4.$inject = ["ctrl4_param1", "ctrl4_param2"]; | ||
]); | ||
/* after */ | ||
myMod.controller("ctrl3", ["ctrl3_param1", "ctrl3_param2", function(ctrl3_param1, ctrl3_param2) { | ||
return x = "ctrl3 body"; | ||
} | ||
]); | ||
})(); | ||
/* @ngInject */ | ||
ctrl4 = function(ctrl4_param1, ctrl4_param2) { | ||
return x = "ctrl4 body"; | ||
}; | ||
ctrl4.$inject = ["ctrl4_param1", "ctrl4_param2"]; | ||
x = "after"; | ||
}).call(this); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
399502
67
10840
4
325