ngannotate-rails 0.9.9 → 0.9.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ODQ2NmUwNTEwZDE5MTA2YzUwZTg2ZGM0NWVlMjM2NzcxYzdhMWM3YQ==
4
+ MWE4NWU5NzAyODRkODQ3ZTE3Y2Q1NWM1ODBkMmIyYzkyZmYzMGY2MA==
5
5
  data.tar.gz: !binary |-
6
- MWNhYWZlMTQ3NzZmYmEzYmYzNzIzNmNjZmI0OThlMGVjYzg5YmJkMw==
6
+ MWY2ZGNlZTEzZmUwYmZiYzA5MmMzYzIzOGVkMzBkNWVmZWY3NzA3OQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YmE0MDM1MGYyNjI2NzEzMzlmNWZiYWE1NGMxNDRiZTk1MzYzMTA4ODYyNzRh
10
- M2VmODNiMzhiOGFhNWVlNTY2MzAyNjY4MjM1OTZmOGFjN2VhMmI1NmFiYzk3
11
- NGQxNzlhZDg1M2ZhMzhkODE4YTUxMmRmOGRhNWYxYTA5NzhkN2M=
9
+ N2I1NzE3YzQ2M2FmOGM4NjU4NDViZmQyYzMwZGQ3NDU4OTRlNmM1YTAxNTFk
10
+ MGM4MDRmOTBjZDQ1Zjc0M2I3OWI3NWRhYjRhZTU3NzRjMzI5ZTdhZjAzODg2
11
+ YmRjMTRlMDBmMTc3ZWI3YmFjMTIzOTMxYzJkNzcyZjU4ZjkyMmY=
12
12
  data.tar.gz: !binary |-
13
- MTkzNDQxZjc3OWFlMmE1MTdkYjcwYjU5OGE3OTAwNmQ5YWQ2ZmY3ZDMzNTZl
14
- MGZiNzlkMzMyNTYwYWNiNjMzMzA4ZWVjZWM5Njc3YTU2NjcyZWJlNmViNWRh
15
- MWI4Mzc1ODk4MzQwODExM2NiMjRmODM3ZjY1NjZlMTNkMThkNTM=
13
+ ZDJkMGNjYTBkNjJlY2EyYWNhMmJhNzI2Y2UzNmZhZDQ1NjIzMGQzZjk3Yjli
14
+ ODNiNjQxYzNlZGQxZTUwY2MzNDEzZDY1MjIyMjQ0OWM2ZDg1NmM1MDc3NWE3
15
+ Y2YyMDkzZjJlOWFiNDE1NGRjN2IxN2Y1ZDlhZTU2NzVlOTQ4OTI=
@@ -1,5 +1,5 @@
1
1
  module Ngannotate
2
2
  module Rails
3
- VERSION = "0.9.9"
3
+ VERSION = "0.9.11"
4
4
  end
5
5
  end
@@ -1414,44 +1414,135 @@ module.exports = function generateSourcemap(src, fragments, inFile, sourceRoot)
1414
1414
  return new SourceMapper(src, fragments, inFile, sourceRoot).generate();
1415
1415
  }
1416
1416
 
1417
- },{"source-map":19,"stable":29}],9:[function(require,module,exports){
1417
+ },{"source-map":20,"stable":30}],9:[function(require,module,exports){
1418
+ // lut.js
1419
+ // MIT licensed, see LICENSE file
1420
+ // Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
1421
+
1418
1422
  "use strict";
1419
1423
 
1420
1424
  var assert = require("assert");
1421
- var PriorityQueue = require("priorityqueuejs");
1425
+ var traverse = require("ordered-ast-traverse");
1426
+ var is = require("simple-is");
1422
1427
 
1423
- function Heap() {
1424
- assert(this instanceof Heap);
1428
+ module.exports = Lut;
1425
1429
 
1426
- var q = new PriorityQueue(function(a, b) {
1427
- return b.pos - a.pos;
1428
- });
1430
+ function Lut(ast, src) {
1431
+ assert(this instanceof Lut);
1429
1432
 
1430
- function nextPos() {
1431
- return (q.size() >= 1 ? q.peek().pos : (1 << 30));
1433
+ var sparseBegins = new Array(src.length);
1434
+ var begins = [];
1435
+ var sparseEnds = new Array(src.length);
1436
+ var ends = [];
1437
+ var p = 0;
1438
+ var t0 = Date.now();
1439
+ traverse(ast, {pre: function(node) {
1440
+ // assert (node.range[0] >= p);
1441
+ if (node.type === "Program") {
1442
+ return;
1443
+ }
1444
+ p = node.range[0];
1445
+ if (!sparseBegins[p]) {
1446
+ sparseBegins[p] = node;
1447
+ }
1448
+ p = node.range[1];
1449
+ if (!sparseEnds[p]) {
1450
+ sparseEnds[p] = node;
1451
+ }
1452
+ }});
1453
+ for (var i in sparseBegins) {
1454
+ begins.push(sparseBegins[i]);
1432
1455
  }
1456
+ for (var i$0 in sparseEnds) {
1457
+ ends.push(sparseEnds[i$0]);
1458
+ }
1459
+ var t1 = Date.now();
1460
+ // console.error(t1-t0)
1433
1461
 
1434
- this.pos = (1 << 30);
1435
- this.addMany = function(arr) {
1436
- arr.forEach(function(e) {
1437
- q.enq(e);
1438
- });
1439
- this.pos = nextPos();
1440
- };
1441
- this.add = function(e) {
1442
- q.enq(e);
1443
- this.pos = nextPos();
1444
- };
1445
- this.getAndRemoveNext = function() {
1446
- var e = q.deq();
1447
- this.pos = nextPos();
1448
- return e;
1449
- };
1462
+ // begins and ends are compact arrays with nodes,
1463
+ // sorted on node.range[0/1] (unique)
1464
+ this.begins = begins;
1465
+ this.ends = ends;
1466
+ }
1467
+
1468
+ Lut.prototype.findNodeFromPos = findNodeFromPos;
1469
+ Lut.prototype.findNodeBeforePos = findNodeBeforePos;
1470
+
1471
+ // binary search lut to find node beginning at pos
1472
+ // or as close after pos as possible. null if none
1473
+ function findNodeFromPos(pos) {
1474
+ var lut = this.begins;
1475
+ assert(is.finitenumber(pos) && pos >= 0);
1476
+
1477
+ var left = 0;
1478
+ var right = lut.length - 1;
1479
+ while (left < right) {
1480
+ var mid = Math.floor((left + right) / 2);
1481
+ assert(mid >= 0 && mid < lut.length);
1482
+ if (pos > lut[mid].range[0]) {
1483
+ left = mid + 1;
1484
+ }
1485
+ else {
1486
+ right = mid;
1487
+ }
1488
+ }
1489
+ if (left > right) {
1490
+ assert(last(lut).range[0] < pos);
1491
+ return null;
1492
+ }
1493
+
1494
+ var found = left;
1495
+ var foundPos = lut[found].range[0];
1496
+ assert(foundPos >= pos);
1497
+ if (found >= 1) {
1498
+ var prevPos = lut[found - 1].range[0];
1499
+ assert(prevPos < pos);
1500
+ }
1501
+
1502
+ return lut[found];
1450
1503
  }
1451
1504
 
1452
- module.exports = Heap;
1505
+ // binary search lut to find node ending (as in range[1]
1506
+ // at or before pos. null if none
1507
+ function findNodeBeforePos(pos) {
1508
+ var lut = this.ends;
1509
+ assert(is.finitenumber(pos) && pos >= 0);
1453
1510
 
1454
- },{"assert":1,"priorityqueuejs":16}],10:[function(require,module,exports){
1511
+ var left = 0;
1512
+ var right = lut.length - 1;
1513
+ while (left < right) {
1514
+ var mid = Math.ceil((left + right) / 2);
1515
+ assert(mid >= 0 && mid < lut.length);
1516
+ if (pos < lut[mid].range[1]) {
1517
+ right = mid - 1;
1518
+ }
1519
+ else {
1520
+ left = mid;
1521
+ }
1522
+ }
1523
+ if (left > right) {
1524
+ assert(lut[0].range[1] > pos);
1525
+ return null;
1526
+ }
1527
+
1528
+ var found = left;
1529
+ var foundPos = lut[found].range[1];
1530
+ if(foundPos > pos) {
1531
+ return null;
1532
+ }
1533
+ if (found <= lut.length - 2) {
1534
+ var nextPos = lut[found + 1].range[1];
1535
+ assert(nextPos > pos);
1536
+ }
1537
+
1538
+ return lut[found];
1539
+ }
1540
+
1541
+ function last(arr) {
1542
+ return arr[arr.length - 1];
1543
+ }
1544
+
1545
+ },{"assert":1,"ordered-ast-traverse":17,"simple-is":19}],10:[function(require,module,exports){
1455
1546
  // ng-annotate-main.js
1456
1547
  // MIT licensed, see LICENSE file
1457
1548
  // Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
@@ -1460,12 +1551,16 @@ module.exports = Heap;
1460
1551
  var esprima_require_t0 = Date.now();
1461
1552
  var esprima = require("esprima").parse;
1462
1553
  var esprima_require_t1 = Date.now();
1554
+ var fmt = require("simple-fmt");
1463
1555
  var is = require("simple-is");
1464
1556
  var alter = require("alter");
1465
1557
  var traverse = require("ordered-ast-traverse");
1466
- var Heap = require("./heap");
1467
- var ngInjectComments = require("./nginject-comments");
1558
+ var EOL = require("os").EOL;
1559
+ var assert = require("assert");
1560
+ var ngInject = require("./nginject");
1468
1561
  var generateSourcemap = require("./generate-sourcemap");
1562
+ var Lut = require("./lut");
1563
+ var scopeTools = require("./scopetools");
1469
1564
 
1470
1565
  var chainedRouteProvider = 1;
1471
1566
  var chainedUrlRouterProvider = 2;
@@ -1806,6 +1901,14 @@ function judgeSuspects(ctx) {
1806
1901
  }
1807
1902
 
1808
1903
  target = jumpOverIife(target);
1904
+ var followedTarget = followReference(target);
1905
+ if (followedTarget) {
1906
+ if (followedTarget.$once) {
1907
+ continue;
1908
+ }
1909
+ followedTarget.$once = true;
1910
+ target = followedTarget;
1911
+ }
1809
1912
 
1810
1913
  if (mode === "rebuild" && isAnnotatedArray(target)) {
1811
1914
  replaceArray(target, fragments, quot);
@@ -1813,6 +1916,121 @@ function judgeSuspects(ctx) {
1813
1916
  removeArray(target, fragments);
1814
1917
  } else if (is.someof(mode, ["add", "rebuild"]) && isFunctionExpressionWithArgs(target)) {
1815
1918
  insertArray(target, fragments, quot);
1919
+ } else {
1920
+ // if it's not array or function-expression, then it's a candidate for foo.$inject = [..]
1921
+ judgeInjectArraySuspect(target, ctx);
1922
+ }
1923
+ }
1924
+ }
1925
+
1926
+ function followReference(node) {
1927
+ if (!scopeTools.isReference(node)) {
1928
+ return null;
1929
+ }
1930
+
1931
+ var scope = node.$scope.lookup(node.name);
1932
+ if (!scope) {
1933
+ return null;
1934
+ }
1935
+
1936
+ var parent = scope.getNode(node.name).$parent;
1937
+ var kind = scope.getKind(node.name);
1938
+ var ptype = parent.type;
1939
+
1940
+ if (is.someof(kind, ["const", "let", "var"])) {
1941
+ assert(ptype === "VariableDeclarator");
1942
+ return parent.init;
1943
+ } else if (kind === "fun") {
1944
+ assert(ptype === "FunctionDeclaration" || ptype === "FunctionExpression")
1945
+ return parent;
1946
+ }
1947
+
1948
+ // other kinds should not be handled ("param", "caught")
1949
+
1950
+ return null;
1951
+ }
1952
+
1953
+ function judgeInjectArraySuspect(node, ctx) {
1954
+ // /*@ngInject*/ var foo = function($scope) {} and
1955
+ // /*@ngInject*/ function foo($scope) {} and
1956
+ // /*@ngInject*/ foo.bar[0] = function($scope) {}
1957
+ var d0 = null;
1958
+ var nr0 = node.range[0];
1959
+ var nr1 = node.range[1];
1960
+ if (node.type === "VariableDeclaration" && node.declarations.length === 1 &&
1961
+ (d0 = node.declarations[0]).init && ctx.isFunctionExpressionWithArgs(d0.init)) {
1962
+ var isSemicolonTerminated = (ctx.src[nr1 - 1] === ";");
1963
+ addRemoveInjectArray(d0.init.params, nr0, isSemicolonTerminated ? nr1 : d0.init.range[1], d0.id.name);
1964
+ } else if (ctx.isFunctionDeclarationWithArgs(node)) {
1965
+ addRemoveInjectArray(node.params, nr0, nr1, node.id.name);
1966
+ } else if (node.type === "ExpressionStatement" && node.expression.type === "AssignmentExpression" &&
1967
+ ctx.isFunctionExpressionWithArgs(node.expression.right)) {
1968
+ var isSemicolonTerminated$0 = (ctx.src[nr1 - 1] === ";");
1969
+ var name = ctx.srcForRange(node.expression.left.range);
1970
+ addRemoveInjectArray(node.expression.right.params, nr0, isSemicolonTerminated$0 ? nr1 : node.expression.right.range[1], name);
1971
+ }
1972
+
1973
+ function getIndent(pos) {
1974
+ var src = ctx.src;
1975
+ var lineStart = src.lastIndexOf("\n", pos - 1) + 1;
1976
+ var i = lineStart;
1977
+ for (; src[i] === " " || src[i] === "\t"; i++) {
1978
+ }
1979
+ return src.slice(lineStart, i);
1980
+ }
1981
+
1982
+ function addRemoveInjectArray(params, posBeforeFunctionDeclaration, posAfterFunctionDeclaration, name) {
1983
+ var indent = getIndent(posAfterFunctionDeclaration);
1984
+
1985
+ var nextNode = ctx.lut.findNodeFromPos(posAfterFunctionDeclaration);
1986
+ var prevNode = ctx.lut.findNodeBeforePos(posBeforeFunctionDeclaration);
1987
+
1988
+ function hasInjectArray(node) {
1989
+ var lvalue;
1990
+ var assignment;
1991
+ return (node && node.type === "ExpressionStatement" && (assignment = node.expression).type === "AssignmentExpression" &&
1992
+ assignment.operator === "=" &&
1993
+ (lvalue = assignment.left).type === "MemberExpression" &&
1994
+ ((lvalue.computed === false && ctx.srcForRange(lvalue.object.range) === name && lvalue.property.name === "$inject") ||
1995
+ (lvalue.computed === true && ctx.srcForRange(lvalue.object.range) === name && lvalue.property.type === "Literal" && lvalue.property.value === "$inject")));
1996
+ }
1997
+
1998
+ function skipNewline(pos) {
1999
+ if (ctx.src[pos] === "\n") {
2000
+ return pos + 1;
2001
+ } else if (ctx.src.slice(pos, pos + 2) === "\r\n") {
2002
+ return pos + 2;
2003
+ }
2004
+ return pos;
2005
+ }
2006
+
2007
+ var hasArrayBefore = hasInjectArray(prevNode);
2008
+ var hasArrayAfter = hasInjectArray(nextNode);
2009
+
2010
+ var hasArray = hasArrayBefore || hasArrayAfter;
2011
+ var start = hasArrayBefore ? prevNode.range[0]: posAfterFunctionDeclaration;
2012
+ var end = hasArrayBefore ? skipNewline(prevNode.range[1]) : nextNode.range[1];
2013
+
2014
+ var str = fmt("{0}{1}{2}.$inject = {3};", EOL, indent, name, ctx.stringify(params, ctx.quot));
2015
+
2016
+ if (ctx.mode === "rebuild" && hasArray) {
2017
+ ctx.fragments.push({
2018
+ start: start,
2019
+ end: end,
2020
+ str: str,
2021
+ });
2022
+ } else if (ctx.mode === "remove" && hasArray) {
2023
+ ctx.fragments.push({
2024
+ start: start,
2025
+ end: end,
2026
+ str: "",
2027
+ });
2028
+ } else if (is.someof(ctx.mode, ["add", "rebuild"]) && !hasArray) {
2029
+ ctx.fragments.push({
2030
+ start: posAfterFunctionDeclaration,
2031
+ end: posAfterFunctionDeclaration,
2032
+ str: str,
2033
+ });
1816
2034
  }
1817
2035
  }
1818
2036
  }
@@ -1881,7 +2099,7 @@ window.annotate = function ngAnnotate(src, options) {
1881
2099
  // Fix Program node range (https://code.google.com/p/esprima/issues/detail?id=541)
1882
2100
  ast.range[0] = 0;
1883
2101
 
1884
- // append a dummy-node to ast to catch any remaining triggers
2102
+ // append a dummy-node to ast so that lut.findNodeFromPos(lastPos) returns something
1885
2103
  ast.body.push({
1886
2104
  type: "DebuggerStatement",
1887
2105
  range: [ast.range[1], ast.range[1]],
@@ -1896,10 +2114,6 @@ window.annotate = function ngAnnotate(src, options) {
1896
2114
  // fragments array, later sent to alter in one shot
1897
2115
  var fragments = [];
1898
2116
 
1899
- // triggers contains functions to trigger when traverse hits the
1900
- // first node at (or after) a certain pos
1901
- var triggers = new Heap();
1902
-
1903
2117
  // suspects is built up with suspect nodes by match.
1904
2118
  // A suspect node will get annotations added / removed if it
1905
2119
  // fulfills the arrayexpression or functionexpression look,
@@ -1908,6 +2122,10 @@ window.annotate = function ngAnnotate(src, options) {
1908
2122
  // context with node.$always = true
1909
2123
  var suspects = [];
1910
2124
 
2125
+ var lut = new Lut(ast, src);
2126
+
2127
+ scopeTools.setupScopeAndReferences(ast);
2128
+
1911
2129
  var ctx = {
1912
2130
  mode: mode,
1913
2131
  quot: quot,
@@ -1918,8 +2136,8 @@ window.annotate = function ngAnnotate(src, options) {
1918
2136
  re: re,
1919
2137
  comments: comments,
1920
2138
  fragments: fragments,
1921
- triggers: triggers,
1922
2139
  suspects: suspects,
2140
+ lut: lut,
1923
2141
  isFunctionExpressionWithArgs: isFunctionExpressionWithArgs,
1924
2142
  isFunctionDeclarationWithArgs: isFunctionDeclarationWithArgs,
1925
2143
  isAnnotatedArray: isAnnotatedArray,
@@ -1940,7 +2158,7 @@ window.annotate = function ngAnnotate(src, options) {
1940
2158
  }
1941
2159
  var matchPluginsOrNull = (plugins.length === 0 ? null : matchPlugins);
1942
2160
 
1943
- ngInjectComments.init(ctx);
2161
+ ngInject.inspectComments(ctx);
1944
2162
  plugins.forEach(function(plugin) {
1945
2163
  plugin.init(ctx);
1946
2164
  });
@@ -1952,13 +2170,9 @@ window.annotate = function ngAnnotate(src, options) {
1952
2170
  if (node.type === "CallExpression") {
1953
2171
  callerIds.push(node);
1954
2172
  recentCaller = node;
2173
+ ngInject.inspectCallExpression(node, ctx);
1955
2174
  }
1956
2175
 
1957
- var pos = node.range[0];
1958
- while (pos >= triggers.pos) {
1959
- var trigger = triggers.getAndRemoveNext();
1960
- trigger.fn.call(null, node, trigger.ctx);
1961
- }
1962
2176
  }, post: function(node) {
1963
2177
  if (node === recentCaller) {
1964
2178
  callerIds.pop();
@@ -1995,33 +2209,71 @@ window.annotate = function ngAnnotate(src, options) {
1995
2209
  return result;
1996
2210
  }
1997
2211
 
1998
- },{"./generate-sourcemap":8,"./heap":9,"./nginject-comments":11,"alter":12,"esprima":13,"ordered-ast-traverse":15,"simple-is":18}],11:[function(require,module,exports){
2212
+ },{"./generate-sourcemap":8,"./lut":9,"./nginject":11,"./scopetools":13,"alter":14,"assert":1,"esprima":15,"ordered-ast-traverse":17,"os":5,"simple-fmt":18,"simple-is":19}],11:[function(require,module,exports){
2213
+ // nginject-comments.js
2214
+ // MIT licensed, see LICENSE file
2215
+ // Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
2216
+
1999
2217
  "use strict";
2000
2218
 
2001
- var os = require("os");
2002
2219
  var is = require("simple-is");
2003
2220
  var fmt = require("simple-fmt");
2004
2221
 
2005
2222
  module.exports = {
2006
- init: ngInjectCommentsInit,
2223
+ inspectComments: inspectComments,
2224
+ inspectCallExpression: inspectCallExpression,
2007
2225
  };
2008
2226
 
2009
- function ngInjectCommentsInit(ctx) {
2227
+ function inspectCallExpression(node, ctx) {
2228
+ if (node.type === "CallExpression" && node.callee.type === "Identifier" && node.callee.name === "ngInject" && node.arguments.length === 1) {
2229
+ addSuspect(node.arguments[0], ctx);
2230
+ }
2231
+ }
2232
+
2233
+ function inspectComments(ctx) {
2010
2234
  var comments = ctx.comments;
2011
- var triggers = [];
2012
2235
  for (var i = 0; i < comments.length; i++) {
2013
2236
  var comment = comments[i];
2014
2237
  var pos = comment.value.indexOf("@ngInject");
2015
- if (pos >= 0) {
2016
- triggers.push({
2017
- pos: comment.range[1],
2018
- fn: visitNodeFollowingNgInjectComment,
2019
- ctx: ctx,
2020
- });
2238
+ if (pos === -1) {
2239
+ continue;
2240
+ }
2241
+
2242
+ var target = ctx.lut.findNodeFromPos(comment.range[1]);
2243
+ if (!target) {
2244
+ continue;
2021
2245
  }
2246
+
2247
+ addSuspect(target, ctx);
2248
+ }
2249
+ }
2250
+
2251
+ function addSuspect(target, ctx) {
2252
+ if (target.type === "ObjectExpression") {
2253
+ // /*@ngInject*/ {f1: function(a), .., {f2: function(b)}}
2254
+ addObjectExpression(target, ctx);
2255
+ } else if (target.type === "AssignmentExpression" && target.right.type === "ObjectExpression") {
2256
+ // /*@ngInject*/ f(x.y = {f1: function(a), .., {f2: function(b)}})
2257
+ addObjectExpression(target.right, ctx);
2258
+ } else if (target.type === "ExpressionStatement" && target.expression.type === "AssignmentExpression" && target.expression.right.type === "ObjectExpression") {
2259
+ // /*@ngInject*/ x.y = {f1: function(a), .., {f2: function(b)}}
2260
+ addObjectExpression(target.expression.right, ctx);
2261
+ } else if (target.type === "VariableDeclaration" && target.declarations.length === 1 && target.declarations[0].init && target.declarations[0].init.type === "ObjectExpression") {
2262
+ // /*@ngInject*/ var x = {f1: function(a), .., {f2: function(b)}}
2263
+ addObjectExpression(target.declarations[0].init, ctx);
2264
+ } else if (target.type === "Property") {
2265
+ // {/*@ngInject*/ justthisone: function(a), ..}
2266
+ ctx.addModuleContextIndependentSuspect(target.value, ctx);
2267
+ } else {
2268
+ // /*@ngInject*/ function(a) {}
2269
+ ctx.addModuleContextIndependentSuspect(target, ctx);
2022
2270
  }
2271
+ }
2023
2272
 
2024
- ctx.triggers.addMany(triggers);
2273
+ function addObjectExpression(node, ctx) {
2274
+ nestedObjectValues(node).forEach(function(n) {
2275
+ ctx.addModuleContextIndependentSuspect(n, ctx);
2276
+ });
2025
2277
  }
2026
2278
 
2027
2279
  function nestedObjectValues(node, res) {
@@ -2039,89 +2291,349 @@ function nestedObjectValues(node, res) {
2039
2291
  return res;
2040
2292
  }
2041
2293
 
2042
- function visitNodeFollowingNgInjectComment(node, ctx) {
2043
- // handle most common case: /*@ngInject*/ prepended to an array or function expression
2044
- // (or call expression, in case of IIFE jumping)
2045
- if (node.type === "ArrayExpression" || node.type === "FunctionExpression" || node.type === "CallExpression") {
2046
- ctx.addModuleContextIndependentSuspect(node, ctx);
2047
- return;
2294
+ },{"simple-fmt":18,"simple-is":19}],12:[function(require,module,exports){
2295
+ // scope.js
2296
+ // MIT licensed, see LICENSE file
2297
+ // Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
2298
+
2299
+ "use strict";
2300
+
2301
+ var assert = require("assert");
2302
+ var stringmap = require("stringmap");
2303
+ var stringset = require("stringset");
2304
+ var is = require("simple-is");
2305
+ var fmt = require("simple-fmt");
2306
+
2307
+ function Scope(args) {
2308
+ assert(is.someof(args.kind, ["hoist", "block", "catch-block"]));
2309
+ assert(is.object(args.node));
2310
+ assert(args.parent === null || is.object(args.parent));
2311
+
2312
+ // kind === "hoist": function scopes, program scope, injected globals
2313
+ // kind === "block": ES6 block scopes
2314
+ // kind === "catch-block": catch block scopes
2315
+ this.kind = args.kind;
2316
+
2317
+ // the AST node the block corresponds to
2318
+ this.node = args.node;
2319
+
2320
+ // parent scope
2321
+ this.parent = args.parent;
2322
+
2323
+ // children scopes for easier traversal (populated internally)
2324
+ this.children = [];
2325
+
2326
+ // scope declarations. decls[variable_name] = {
2327
+ // kind: "fun" for functions,
2328
+ // "param" for function parameters,
2329
+ // "caught" for catch parameter
2330
+ // "var",
2331
+ // "const",
2332
+ // "let"
2333
+ // node: the AST node the declaration corresponds to
2334
+ // from: source code index from which it is visible at earliest
2335
+ // (only stored for "const", "let" [and "var"] nodes)
2336
+ // }
2337
+ this.decls = stringmap();
2338
+
2339
+ // names of all variables declared outside this hoist scope but
2340
+ // referenced in this scope (immediately or in child).
2341
+ // only stored on hoist scopes for efficiency
2342
+ // (because we currently generate lots of empty block scopes)
2343
+ this.propagates = (this.kind === "hoist" ? stringset() : null);
2344
+
2345
+ // scopes register themselves with their parents for easier traversal
2346
+ if (this.parent) {
2347
+ this.parent.children.push(this);
2048
2348
  }
2349
+ }
2049
2350
 
2050
- if (node.type === "ObjectExpression") {
2051
- nestedObjectValues(node).forEach(function(n) {
2052
- ctx.addModuleContextIndependentSuspect(n, ctx);
2053
- });
2054
- return;
2351
+ Scope.prototype.print = function(indent) {
2352
+ indent = indent || 0;
2353
+ var scope = this;
2354
+ var names = this.decls.keys().map(function(name) {
2355
+ return fmt("{0} [{1}]", name, scope.decls.get(name).kind);
2356
+ }).join(", ");
2357
+ var propagates = this.propagates ? this.propagates.items().join(", ") : "";
2358
+ console.log(fmt("{0}{1}: {2}. propagates: {3}", fmt.repeat(" ", indent), this.node.type, names, propagates));
2359
+ this.children.forEach(function(c) {
2360
+ c.print(indent + 2);
2361
+ });
2362
+ };
2363
+
2364
+ Scope.prototype.add = function(name, kind, node, referableFromPos) {
2365
+ assert(is.someof(kind, ["fun", "param", "var", "caught", "const", "let"]));
2366
+
2367
+ function isConstLet(kind) {
2368
+ return is.someof(kind, ["const", "let"]);
2055
2369
  }
2056
2370
 
2057
- // /*@ngInject*/ var foo = function($scope) {} and
2058
- // /*@ngInject*/ function foo($scope) {}
2059
- var d0 = null;
2060
- var nr1 = node.range[1];
2061
- if (node.type === "VariableDeclaration" && node.declarations.length === 1 &&
2062
- (d0 = node.declarations[0]).init && ctx.isFunctionExpressionWithArgs(d0.init)) {
2063
- var isSemicolonTerminated = (ctx.src[nr1 - 1] === ";");
2064
- addRemoveInjectArray(d0.init.params, isSemicolonTerminated ? nr1 : d0.init.range[1], d0.id.name);
2065
- } else if (ctx.isFunctionDeclarationWithArgs(node)) {
2066
- addRemoveInjectArray(node.params, nr1, node.id.name);
2067
- } else if (node.type === "ExpressionStatement" && node.expression.type === "AssignmentExpression" &&
2068
- ctx.isFunctionExpressionWithArgs(node.expression.right)) {
2069
- var isSemicolonTerminated$0 = (ctx.src[nr1 - 1] === ";");
2070
- var name = ctx.srcForRange(node.expression.left.range);
2071
- addRemoveInjectArray(node.expression.right.params, isSemicolonTerminated$0 ? nr1 : node.expression.right.range[1], name);
2371
+ var scope = this;
2372
+
2373
+ // search nearest hoist-scope for fun, param and var's
2374
+ // const, let and caught variables go directly in the scope (which may be hoist, block or catch-block)
2375
+ if (is.someof(kind, ["fun", "param", "var"])) {
2376
+ while (scope.kind !== "hoist") {
2377
+ // if (scope.decls.has(name) && isConstLet(scope.decls.get(name).kind)) { // could be caught
2378
+ // return error(getline(node), "{0} is already declared", name);
2379
+ // }
2380
+ scope = scope.parent;
2381
+ }
2072
2382
  }
2383
+ // name exists in scope and either new or existing kind is const|let => error
2384
+ // if (scope.decls.has(name) && (isConstLet(scope.decls.get(name).kind) || isConstLet(kind))) {
2385
+ // return error(getline(node), "{0} is already declared", name);
2386
+ // }
2073
2387
 
2074
- function getIndent(pos) {
2075
- var src = ctx.src;
2076
- var lineStart = src.lastIndexOf("\n", pos - 1) + 1;
2077
- var i = lineStart;
2078
- for (; src[i] === " " || src[i] === "\t"; i++) {
2388
+ var declaration = {
2389
+ kind: kind,
2390
+ node: node,
2391
+ };
2392
+ if (referableFromPos) {
2393
+ assert(is.someof(kind, ["var", "const", "let"]));
2394
+ declaration.from = referableFromPos;
2395
+ }
2396
+ scope.decls.set(name, declaration);
2397
+ };
2398
+
2399
+ Scope.prototype.getKind = function(name) {
2400
+ assert(is.string(name));
2401
+ var decl = this.decls.get(name);
2402
+ return decl ? decl.kind : null;
2403
+ };
2404
+
2405
+ Scope.prototype.getNode = function(name) {
2406
+ assert(is.string(name));
2407
+ var decl = this.decls.get(name);
2408
+ return decl ? decl.node : null;
2409
+ };
2410
+
2411
+ Scope.prototype.getFromPos = function(name) {
2412
+ assert(is.string(name));
2413
+ var decl = this.decls.get(name);
2414
+ return decl ? decl.from : null;
2415
+ };
2416
+
2417
+ Scope.prototype.hasOwn = function(name) {
2418
+ return this.decls.has(name);
2419
+ };
2420
+
2421
+ Scope.prototype.remove = function(name) {
2422
+ return this.decls.remove(name);
2423
+ };
2424
+
2425
+ Scope.prototype.doesPropagate = function(name) {
2426
+ return this.propagates.has(name);
2427
+ };
2428
+
2429
+ Scope.prototype.markPropagates = function(name) {
2430
+ this.propagates.add(name);
2431
+ };
2432
+
2433
+ Scope.prototype.closestHoistScope = function() {
2434
+ var scope = this;
2435
+ while (scope.kind !== "hoist") {
2436
+ scope = scope.parent;
2437
+ }
2438
+ return scope;
2439
+ };
2440
+
2441
+ Scope.prototype.lookup = function(name) {
2442
+ for (var scope = this; scope; scope = scope.parent) {
2443
+ if (scope.decls.has(name)) {
2444
+ return scope;
2445
+ } else if (scope.kind === "hoist") {
2446
+ scope.propagates.add(name);
2079
2447
  }
2080
- return src.slice(lineStart, i);
2081
2448
  }
2449
+ return null;
2450
+ };
2082
2451
 
2083
- function addRemoveInjectArray(params, posAfterFunctionDeclaration, name) {
2084
- var indent = getIndent(posAfterFunctionDeclaration);
2085
- var str = fmt("{0}{1}{2}.$inject = {3};", os.EOL, indent, name, ctx.stringify(params, ctx.quot));
2452
+ module.exports = Scope;
2453
+
2454
+ },{"assert":1,"simple-fmt":18,"simple-is":19,"stringmap":31,"stringset":32}],13:[function(require,module,exports){
2455
+ // scopetools.js
2456
+ // MIT licensed, see LICENSE file
2457
+ // Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
2458
+
2459
+ "use strict";
2086
2460
 
2087
- ctx.triggers.add({
2088
- pos: posAfterFunctionDeclaration,
2089
- fn: visitNodeFollowingFunctionDeclaration,
2461
+ var assert = require("assert");
2462
+ var traverse = require("ordered-ast-traverse");
2463
+ var Scope = require("./scope");
2464
+ var is = require("simple-is");
2465
+
2466
+ module.exports = {
2467
+ setupScopeAndReferences: setupScopeAndReferences,
2468
+ isReference: isReference,
2469
+ };
2470
+
2471
+ function setupScopeAndReferences(root) {
2472
+ traverse(root, {pre: createScopes});
2473
+ createTopScope(root.$scope);
2474
+ }
2475
+
2476
+ function createScopes(node, parent) {
2477
+ node.$parent = parent;
2478
+ node.$scope = parent ? parent.$scope : null; // may be overridden
2479
+
2480
+ if (isNonFunctionBlock(node, parent)) {
2481
+ // A block node is a scope unless parent is a function
2482
+ node.$scope = new Scope({
2483
+ kind: "block",
2484
+ node: node,
2485
+ parent: parent.$scope,
2090
2486
  });
2091
2487
 
2092
- function visitNodeFollowingFunctionDeclaration(nextNode) {
2093
- var assignment = nextNode.expression;
2094
- var lvalue;
2095
- var hasInjectArray = (nextNode.type === "ExpressionStatement" && assignment.type === "AssignmentExpression" &&
2096
- assignment.operator === "=" &&
2097
- (lvalue = assignment.left).type === "MemberExpression" &&
2098
- lvalue.computed === false && ctx.srcForRange(lvalue.object.range) === name && lvalue.property.name === "$inject");
2488
+ } else if (node.type === "VariableDeclaration") {
2489
+ // Variable declarations names goes in current scope
2490
+ node.declarations.forEach(function(declarator) {
2491
+ var name = declarator.id.name;
2492
+ node.$scope.add(name, node.kind, declarator.id, declarator.range[1]);
2493
+ });
2099
2494
 
2100
- if (ctx.mode === "rebuild" && hasInjectArray) {
2101
- ctx.fragments.push({
2102
- start: posAfterFunctionDeclaration,
2103
- end: nextNode.range[1],
2104
- str: str,
2105
- });
2106
- } else if (ctx.mode === "remove" && hasInjectArray) {
2107
- ctx.fragments.push({
2108
- start: posAfterFunctionDeclaration,
2109
- end: nextNode.range[1],
2110
- str: "",
2111
- });
2112
- } else if (is.someof(ctx.mode, ["add", "rebuild"]) && !hasInjectArray) {
2113
- ctx.fragments.push({
2114
- start: posAfterFunctionDeclaration,
2115
- end: posAfterFunctionDeclaration,
2116
- str: str,
2117
- });
2495
+ } else if (isFunction(node)) {
2496
+ // Function is a scope, with params in it
2497
+ // There's no block-scope under it
2498
+
2499
+ node.$scope = new Scope({
2500
+ kind: "hoist",
2501
+ node: node,
2502
+ parent: parent.$scope,
2503
+ });
2504
+
2505
+ // function has a name
2506
+ if (node.id) {
2507
+ if (node.type === "FunctionDeclaration") {
2508
+ // Function name goes in parent scope for declared functions
2509
+ parent.$scope.add(node.id.name, "fun", node.id, null);
2510
+ } else if (node.type === "FunctionExpression") {
2511
+ // Function name goes in function's scope for named function expressions
2512
+ node.$scope.add(node.id.name, "fun", node.id, null);
2513
+ } else {
2514
+ assert(false);
2118
2515
  }
2119
2516
  }
2517
+
2518
+ node.params.forEach(function(param) {
2519
+ node.$scope.add(param.name, "param", param, null);
2520
+ });
2521
+
2522
+ } else if (isForWithConstLet(node) || isForInOfWithConstLet(node)) {
2523
+ // For(In/Of) loop with const|let declaration is a scope, with declaration in it
2524
+ // There may be a block-scope under it
2525
+ node.$scope = new Scope({
2526
+ kind: "block",
2527
+ node: node,
2528
+ parent: parent.$scope,
2529
+ });
2530
+
2531
+ } else if (node.type === "CatchClause") {
2532
+ var identifier = node.param;
2533
+
2534
+ node.$scope = new Scope({
2535
+ kind: "catch-block",
2536
+ node: node,
2537
+ parent: parent.$scope,
2538
+ });
2539
+ node.$scope.add(identifier.name, "caught", identifier, null);
2540
+
2541
+ // All hoist-scope keeps track of which variables that are propagated through,
2542
+ // i.e. an reference inside the scope points to a declaration outside the scope.
2543
+ // This is used to mark "taint" the name since adding a new variable in the scope,
2544
+ // with a propagated name, would change the meaning of the existing references.
2545
+ //
2546
+ // catch(e) is special because even though e is a variable in its own scope,
2547
+ // we want to make sure that catch(e){let e} is never transformed to
2548
+ // catch(e){var e} (but rather var e$0). For that reason we taint the use of e
2549
+ // in the closest hoist-scope, i.e. where var e$0 belongs.
2550
+ node.$scope.closestHoistScope().markPropagates(identifier.name);
2551
+
2552
+ } else if (node.type === "Program") {
2553
+ // Top-level program is a scope
2554
+ // There's no block-scope under it
2555
+ node.$scope = new Scope({
2556
+ kind: "hoist",
2557
+ node: node,
2558
+ parent: null,
2559
+ });
2120
2560
  }
2121
2561
  }
2122
2562
 
2563
+ function createTopScope(programScope) {
2564
+ function inject(obj) {
2565
+ for (var name in obj) {
2566
+ var writeable = obj[name];
2567
+ var kind = (writeable ? "var" : "const");
2568
+ if (topScope.hasOwn(name)) {
2569
+ topScope.remove(name);
2570
+ }
2571
+ topScope.add(name, kind, {loc: {start: {line: -1}}}, -1);
2572
+ }
2573
+ }
2123
2574
 
2124
- },{"os":5,"simple-fmt":17,"simple-is":18}],12:[function(require,module,exports){
2575
+ var topScope = new Scope({
2576
+ kind: "hoist",
2577
+ node: {},
2578
+ parent: null,
2579
+ });
2580
+
2581
+ var complementary = {
2582
+ undefined: false,
2583
+ Infinity: false,
2584
+ console: false,
2585
+ };
2586
+
2587
+ inject(complementary);
2588
+ // inject(jshint_vars.reservedVars);
2589
+ // inject(jshint_vars.ecmaIdentifiers);
2590
+
2591
+ // link it in
2592
+ programScope.parent = topScope;
2593
+ topScope.children.push(programScope);
2594
+
2595
+ return topScope;
2596
+ }
2597
+
2598
+ function isConstLet(kind) {
2599
+ return kind === "const" || kind === "let";
2600
+ }
2601
+
2602
+ function isNonFunctionBlock(node, parent) {
2603
+ return node.type === "BlockStatement" && parent.type !== "FunctionDeclaration" && parent.type !== "FunctionExpression";
2604
+ }
2605
+
2606
+ function isForWithConstLet(node) {
2607
+ return node.type === "ForStatement" && node.init && node.init.type === "VariableDeclaration" && isConstLet(node.init.kind);
2608
+ }
2609
+
2610
+ function isForInOfWithConstLet(node) {
2611
+ return isForInOf(node) && node.left.type === "VariableDeclaration" && isConstLet(node.left.kind);
2612
+ }
2613
+
2614
+ function isForInOf(node) {
2615
+ return node.type === "ForInStatement" || node.type === "ForOfStatement";
2616
+ }
2617
+
2618
+ function isFunction(node) {
2619
+ return node.type === "FunctionDeclaration" || node.type === "FunctionExpression";
2620
+ }
2621
+
2622
+ function isReference(node) {
2623
+ var parent = node.$parent;
2624
+ return node.$refToScope ||
2625
+ node.type === "Identifier" &&
2626
+ !(parent.type === "VariableDeclarator" && parent.id === node) && // var|let|const $
2627
+ !(parent.type === "MemberExpression" && parent.computed === false && parent.property === node) && // obj.$
2628
+ !(parent.type === "Property" && parent.key === node) && // {$: ...}
2629
+ !(parent.type === "LabeledStatement" && parent.label === node) && // $: ...
2630
+ !(parent.type === "CatchClause" && parent.param === node) && // catch($)
2631
+ !(isFunction(parent) && parent.id === node) && // function $(..
2632
+ !(isFunction(parent) && is.someof(node, parent.params)) && // function f($)..
2633
+ true;
2634
+ }
2635
+
2636
+ },{"./scope":12,"assert":1,"ordered-ast-traverse":17,"simple-is":19}],14:[function(require,module,exports){
2125
2637
  // alter.js
2126
2638
  // MIT licensed, see LICENSE file
2127
2639
  // Copyright (c) 2013 Olov Lassus <olov.lassus@gmail.com>
@@ -2168,7 +2680,7 @@ if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
2168
2680
  module.exports = alter;
2169
2681
  }
2170
2682
 
2171
- },{"assert":1,"stable":29}],13:[function(require,module,exports){
2683
+ },{"assert":1,"stable":30}],15:[function(require,module,exports){
2172
2684
  /*
2173
2685
  Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>
2174
2686
  Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>
@@ -5926,7 +6438,7 @@ parseStatement: true, parseSourceElement: true */
5926
6438
  }));
5927
6439
  /* vim: set sw=4 ts=4 et tw=80 : */
5928
6440
 
5929
- },{}],14:[function(require,module,exports){
6441
+ },{}],16:[function(require,module,exports){
5930
6442
  // ordered-esprima-props.js
5931
6443
  // MIT licensed, see LICENSE file
5932
6444
  // Copyright (c) 2014 Olov Lassus <olov.lassus@gmail.com>
@@ -6005,7 +6517,7 @@ module.exports = (function() {
6005
6517
  };
6006
6518
  })();
6007
6519
 
6008
- },{}],15:[function(require,module,exports){
6520
+ },{}],17:[function(require,module,exports){
6009
6521
  // ordered-ast-traverse.js
6010
6522
  // MIT licensed, see LICENSE file
6011
6523
  // Copyright (c) 2014 Olov Lassus <olov.lassus@gmail.com>
@@ -6066,181 +6578,7 @@ if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
6066
6578
  module.exports = traverse;
6067
6579
  }
6068
6580
 
6069
- },{"ordered-esprima-props":14}],16:[function(require,module,exports){
6070
- /**
6071
- * Expose `PriorityQueue`.
6072
- */
6073
- module.exports = PriorityQueue;
6074
-
6075
- /**
6076
- * Initializes a new empty `PriorityQueue` with the given `comparator(a, b)`
6077
- * function, uses `.DEFAULT_COMPARATOR()` when no function is provided.
6078
- *
6079
- * The comparator function must return a positive number when `a > b`, 0 when
6080
- * `a == b` and a negative number when `a < b`.
6081
- *
6082
- * @param {Function}
6083
- * @return {PriorityQueue}
6084
- * @api public
6085
- */
6086
- function PriorityQueue(comparator) {
6087
- this._comparator = comparator || PriorityQueue.DEFAULT_COMPARATOR;
6088
- this._elements = [];
6089
- }
6090
-
6091
- /**
6092
- * Compares `a` and `b`, when `a > b` it returns a positive number, when
6093
- * it returns 0 and when `a < b` it returns a negative number.
6094
- *
6095
- * @param {String|Number} a
6096
- * @param {String|Number} b
6097
- * @return {Number}
6098
- * @api public
6099
- */
6100
- PriorityQueue.DEFAULT_COMPARATOR = function(a, b) {
6101
- if (a instanceof Number && b instanceof Number) {
6102
- return a - b;
6103
- } else {
6104
- a = a.toString();
6105
- b = b.toString();
6106
-
6107
- if (a == b) return 0;
6108
-
6109
- return (a > b) ? 1 : -1;
6110
- }
6111
- };
6112
-
6113
- /**
6114
- * Returns whether the priority queue is empty or not.
6115
- *
6116
- * @return {Boolean}
6117
- * @api public
6118
- */
6119
- PriorityQueue.prototype.isEmpty = function() {
6120
- return this.size() === 0;
6121
- };
6122
-
6123
- /**
6124
- * Peeks at the top element of the priority queue.
6125
- *
6126
- * @return {Object}
6127
- * @throws {Error} when the queue is empty.
6128
- * @api public
6129
- */
6130
- PriorityQueue.prototype.peek = function() {
6131
- if (this.isEmpty()) throw new Error('PriorityQueue is empty');
6132
-
6133
- return this._elements[0];
6134
- };
6135
-
6136
- /**
6137
- * Dequeues the top element of the priority queue.
6138
- *
6139
- * @return {Object}
6140
- * @throws {Error} when the queue is empty.
6141
- * @api public
6142
- */
6143
- PriorityQueue.prototype.deq = function() {
6144
- var first = this.peek();
6145
- var last = this._elements.pop();
6146
- var size = this.size();
6147
-
6148
- if (size === 0) return first;
6149
-
6150
- this._elements[0] = last;
6151
- var current = 0;
6152
-
6153
- while (current < size) {
6154
- var largest = current;
6155
- var left = (2 * current) + 1;
6156
- var right = (2 * current) + 2;
6157
-
6158
- if (left < size && this._compare(left, largest) > 0) {
6159
- largest = left;
6160
- }
6161
-
6162
- if (right < size && this._compare(right, largest) > 0) {
6163
- largest = right;
6164
- }
6165
-
6166
- if (largest === current) break;
6167
-
6168
- this._swap(largest, current);
6169
- current = largest;
6170
- }
6171
-
6172
- return first;
6173
- };
6174
-
6175
- /**
6176
- * Enqueues the `element` at the priority queue and returns its new size.
6177
- *
6178
- * @param {Object} element
6179
- * @return {Number}
6180
- * @api public
6181
- */
6182
- PriorityQueue.prototype.enq = function(element) {
6183
- var size = this._elements.push(element);
6184
- var current = size - 1;
6185
-
6186
- while (current > 0) {
6187
- var parent = Math.floor((current - 1) / 2);
6188
-
6189
- if (this._compare(current, parent) < 0) break;
6190
-
6191
- this._swap(parent, current);
6192
- current = parent;
6193
- }
6194
-
6195
- return size;
6196
- };
6197
-
6198
- /**
6199
- * Returns the size of the priority queue.
6200
- *
6201
- * @return {Number}
6202
- * @api public
6203
- */
6204
- PriorityQueue.prototype.size = function() {
6205
- return this._elements.length;
6206
- };
6207
-
6208
- /**
6209
- * Iterates over queue elements
6210
- *
6211
- * @param {Function} fn
6212
- */
6213
- PriorityQueue.prototype.forEach = function(fn) {
6214
- return this._elements.forEach(fn);
6215
- };
6216
-
6217
- /**
6218
- * Compares the values at position `a` and `b` in the priority queue using its
6219
- * comparator function.
6220
- *
6221
- * @param {Number} a
6222
- * @param {Number} b
6223
- * @return {Number}
6224
- * @api private
6225
- */
6226
- PriorityQueue.prototype._compare = function(a, b) {
6227
- return this._comparator(this._elements[a], this._elements[b]);
6228
- };
6229
-
6230
- /**
6231
- * Swaps the values at position `a` and `b` in the priority queue.
6232
- *
6233
- * @param {Number} a
6234
- * @param {Number} b
6235
- * @api private
6236
- */
6237
- PriorityQueue.prototype._swap = function(a, b) {
6238
- var aux = this._elements[a];
6239
- this._elements[a] = this._elements[b];
6240
- this._elements[b] = aux;
6241
- };
6242
-
6243
- },{}],17:[function(require,module,exports){
6581
+ },{"ordered-esprima-props":16}],18:[function(require,module,exports){
6244
6582
  // simple-fmt.js
6245
6583
  // MIT licensed, see LICENSE file
6246
6584
  // Copyright (c) 2013 Olov Lassus <olov.lassus@gmail.com>
@@ -6275,7 +6613,7 @@ if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
6275
6613
  module.exports = fmt;
6276
6614
  }
6277
6615
 
6278
- },{}],18:[function(require,module,exports){
6616
+ },{}],19:[function(require,module,exports){
6279
6617
  // simple-is.js
6280
6618
  // MIT licensed, see LICENSE file
6281
6619
  // Copyright (c) 2013 Olov Lassus <olov.lassus@gmail.com>
@@ -6333,7 +6671,7 @@ if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
6333
6671
  module.exports = is;
6334
6672
  }
6335
6673
 
6336
- },{}],19:[function(require,module,exports){
6674
+ },{}],20:[function(require,module,exports){
6337
6675
  /*
6338
6676
  * Copyright 2009-2011 Mozilla Foundation and contributors
6339
6677
  * Licensed under the New BSD license. See LICENSE.txt or:
@@ -6343,7 +6681,7 @@ exports.SourceMapGenerator = require('./source-map/source-map-generator').Source
6343
6681
  exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer;
6344
6682
  exports.SourceNode = require('./source-map/source-node').SourceNode;
6345
6683
 
6346
- },{"./source-map/source-map-consumer":24,"./source-map/source-map-generator":25,"./source-map/source-node":26}],20:[function(require,module,exports){
6684
+ },{"./source-map/source-map-consumer":25,"./source-map/source-map-generator":26,"./source-map/source-node":27}],21:[function(require,module,exports){
6347
6685
  /* -*- Mode: js; js-indent-level: 2; -*- */
6348
6686
  /*
6349
6687
  * Copyright 2011 Mozilla Foundation and contributors
@@ -6442,7 +6780,7 @@ define(function (require, exports, module) {
6442
6780
 
6443
6781
  });
6444
6782
 
6445
- },{"./util":27,"amdefine":28}],21:[function(require,module,exports){
6783
+ },{"./util":28,"amdefine":29}],22:[function(require,module,exports){
6446
6784
  /* -*- Mode: js; js-indent-level: 2; -*- */
6447
6785
  /*
6448
6786
  * Copyright 2011 Mozilla Foundation and contributors
@@ -6588,7 +6926,7 @@ define(function (require, exports, module) {
6588
6926
 
6589
6927
  });
6590
6928
 
6591
- },{"./base64":22,"amdefine":28}],22:[function(require,module,exports){
6929
+ },{"./base64":23,"amdefine":29}],23:[function(require,module,exports){
6592
6930
  /* -*- Mode: js; js-indent-level: 2; -*- */
6593
6931
  /*
6594
6932
  * Copyright 2011 Mozilla Foundation and contributors
@@ -6632,7 +6970,7 @@ define(function (require, exports, module) {
6632
6970
 
6633
6971
  });
6634
6972
 
6635
- },{"amdefine":28}],23:[function(require,module,exports){
6973
+ },{"amdefine":29}],24:[function(require,module,exports){
6636
6974
  /* -*- Mode: js; js-indent-level: 2; -*- */
6637
6975
  /*
6638
6976
  * Copyright 2011 Mozilla Foundation and contributors
@@ -6715,7 +7053,7 @@ define(function (require, exports, module) {
6715
7053
 
6716
7054
  });
6717
7055
 
6718
- },{"amdefine":28}],24:[function(require,module,exports){
7056
+ },{"amdefine":29}],25:[function(require,module,exports){
6719
7057
  /* -*- Mode: js; js-indent-level: 2; -*- */
6720
7058
  /*
6721
7059
  * Copyright 2011 Mozilla Foundation and contributors
@@ -7195,7 +7533,7 @@ define(function (require, exports, module) {
7195
7533
 
7196
7534
  });
7197
7535
 
7198
- },{"./array-set":20,"./base64-vlq":21,"./binary-search":23,"./util":27,"amdefine":28}],25:[function(require,module,exports){
7536
+ },{"./array-set":21,"./base64-vlq":22,"./binary-search":24,"./util":28,"amdefine":29}],26:[function(require,module,exports){
7199
7537
  /* -*- Mode: js; js-indent-level: 2; -*- */
7200
7538
  /*
7201
7539
  * Copyright 2011 Mozilla Foundation and contributors
@@ -7600,7 +7938,7 @@ define(function (require, exports, module) {
7600
7938
 
7601
7939
  });
7602
7940
 
7603
- },{"./array-set":20,"./base64-vlq":21,"./util":27,"amdefine":28}],26:[function(require,module,exports){
7941
+ },{"./array-set":21,"./base64-vlq":22,"./util":28,"amdefine":29}],27:[function(require,module,exports){
7604
7942
  /* -*- Mode: js; js-indent-level: 2; -*- */
7605
7943
  /*
7606
7944
  * Copyright 2011 Mozilla Foundation and contributors
@@ -8010,7 +8348,7 @@ define(function (require, exports, module) {
8010
8348
 
8011
8349
  });
8012
8350
 
8013
- },{"./source-map-generator":25,"./util":27,"amdefine":28}],27:[function(require,module,exports){
8351
+ },{"./source-map-generator":26,"./util":28,"amdefine":29}],28:[function(require,module,exports){
8014
8352
  /* -*- Mode: js; js-indent-level: 2; -*- */
8015
8353
  /*
8016
8354
  * Copyright 2011 Mozilla Foundation and contributors
@@ -8331,7 +8669,7 @@ define(function (require, exports, module) {
8331
8669
 
8332
8670
  });
8333
8671
 
8334
- },{"amdefine":28}],28:[function(require,module,exports){
8672
+ },{"amdefine":29}],29:[function(require,module,exports){
8335
8673
  (function (process,__filename){
8336
8674
  /** vim: et:ts=4:sw=4:sts=4
8337
8675
  * @license amdefine 0.1.0 Copyright (c) 2011, The Dojo Foundation All Rights Reserved.
@@ -8634,7 +8972,7 @@ function amdefine(module, requireFn) {
8634
8972
  module.exports = amdefine;
8635
8973
 
8636
8974
  }).call(this,require('_process'),"/node_modules/ng-annotate/node_modules/source-map/node_modules/amdefine/amdefine.js")
8637
- },{"_process":7,"path":6}],29:[function(require,module,exports){
8975
+ },{"_process":7,"path":6}],30:[function(require,module,exports){
8638
8976
  //! stable.js 0.1.5, https://github.com/Two-Screen/stable
8639
8977
  //! © 2014 Angry Bytes and contributors. MIT licensed.
8640
8978
 
@@ -8747,4 +9085,433 @@ else {
8747
9085
 
8748
9086
  })();
8749
9087
 
9088
+ },{}],31:[function(require,module,exports){
9089
+ // stringmap.js
9090
+ // MIT licensed, see LICENSE file
9091
+ // Copyright (c) 2013 Olov Lassus <olov.lassus@gmail.com>
9092
+
9093
+ var StringMap = (function() {
9094
+ "use strict";
9095
+
9096
+ // to save us a few characters
9097
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
9098
+
9099
+ var create = (function() {
9100
+ function hasOwnEnumerableProps(obj) {
9101
+ for (var prop in obj) {
9102
+ if (hasOwnProperty.call(obj, prop)) {
9103
+ return true;
9104
+ }
9105
+ }
9106
+ return false;
9107
+ }
9108
+ // FF <= 3.6:
9109
+ // o = {}; o.hasOwnProperty("__proto__" or "__count__" or "__parent__") => true
9110
+ // o = {"__proto__": null}; Object.prototype.hasOwnProperty.call(o, "__proto__" or "__count__" or "__parent__") => false
9111
+ function hasOwnPollutedProps(obj) {
9112
+ return hasOwnProperty.call(obj, "__count__") || hasOwnProperty.call(obj, "__parent__");
9113
+ }
9114
+
9115
+ var useObjectCreate = false;
9116
+ if (typeof Object.create === "function") {
9117
+ if (!hasOwnEnumerableProps(Object.create(null))) {
9118
+ useObjectCreate = true;
9119
+ }
9120
+ }
9121
+ if (useObjectCreate === false) {
9122
+ if (hasOwnEnumerableProps({})) {
9123
+ throw new Error("StringMap environment error 0, please file a bug at https://github.com/olov/stringmap/issues");
9124
+ }
9125
+ }
9126
+ // no throw yet means we can create objects without own enumerable props (safe-guard against VMs and shims)
9127
+
9128
+ var o = (useObjectCreate ? Object.create(null) : {});
9129
+ var useProtoClear = false;
9130
+ if (hasOwnPollutedProps(o)) {
9131
+ o.__proto__ = null;
9132
+ if (hasOwnEnumerableProps(o) || hasOwnPollutedProps(o)) {
9133
+ throw new Error("StringMap environment error 1, please file a bug at https://github.com/olov/stringmap/issues");
9134
+ }
9135
+ useProtoClear = true;
9136
+ }
9137
+ // no throw yet means we can create objects without own polluted props (safe-guard against VMs and shims)
9138
+
9139
+ return function() {
9140
+ var o = (useObjectCreate ? Object.create(null) : {});
9141
+ if (useProtoClear) {
9142
+ o.__proto__ = null;
9143
+ }
9144
+ return o;
9145
+ };
9146
+ })();
9147
+
9148
+ // stringmap ctor
9149
+ function stringmap(optional_object) {
9150
+ // use with or without new
9151
+ if (!(this instanceof stringmap)) {
9152
+ return new stringmap(optional_object);
9153
+ }
9154
+ this.obj = create();
9155
+ this.hasProto = false; // false (no __proto__ key) or true (has __proto__ key)
9156
+ this.proto = undefined; // value for __proto__ key when hasProto is true, undefined otherwise
9157
+
9158
+ if (optional_object) {
9159
+ this.setMany(optional_object);
9160
+ }
9161
+ };
9162
+
9163
+ // primitive methods that deals with data representation
9164
+ stringmap.prototype.has = function(key) {
9165
+ // The type-check of key in has, get, set and delete is important because otherwise an object
9166
+ // {toString: function() { return "__proto__"; }} can avoid the key === "__proto__" test.
9167
+ // The alternative to type-checking would be to force string conversion, i.e. key = String(key);
9168
+ if (typeof key !== "string") {
9169
+ throw new Error("StringMap expected string key");
9170
+ }
9171
+ return (key === "__proto__" ?
9172
+ this.hasProto :
9173
+ hasOwnProperty.call(this.obj, key));
9174
+ };
9175
+
9176
+ stringmap.prototype.get = function(key) {
9177
+ if (typeof key !== "string") {
9178
+ throw new Error("StringMap expected string key");
9179
+ }
9180
+ return (key === "__proto__" ?
9181
+ this.proto :
9182
+ (hasOwnProperty.call(this.obj, key) ? this.obj[key] : undefined));
9183
+ };
9184
+
9185
+ stringmap.prototype.set = function(key, value) {
9186
+ if (typeof key !== "string") {
9187
+ throw new Error("StringMap expected string key");
9188
+ }
9189
+ if (key === "__proto__") {
9190
+ this.hasProto = true;
9191
+ this.proto = value;
9192
+ } else {
9193
+ this.obj[key] = value;
9194
+ }
9195
+ };
9196
+
9197
+ stringmap.prototype.remove = function(key) {
9198
+ if (typeof key !== "string") {
9199
+ throw new Error("StringMap expected string key");
9200
+ }
9201
+ var didExist = this.has(key);
9202
+ if (key === "__proto__") {
9203
+ this.hasProto = false;
9204
+ this.proto = undefined;
9205
+ } else {
9206
+ delete this.obj[key];
9207
+ }
9208
+ return didExist;
9209
+ };
9210
+
9211
+ // alias remove to delete but beware:
9212
+ // sm.delete("key"); // OK in ES5 and later
9213
+ // sm['delete']("key"); // OK in all ES versions
9214
+ // sm.remove("key"); // OK in all ES versions
9215
+ stringmap.prototype['delete'] = stringmap.prototype.remove;
9216
+
9217
+ stringmap.prototype.isEmpty = function() {
9218
+ for (var key in this.obj) {
9219
+ if (hasOwnProperty.call(this.obj, key)) {
9220
+ return false;
9221
+ }
9222
+ }
9223
+ return !this.hasProto;
9224
+ };
9225
+
9226
+ stringmap.prototype.size = function() {
9227
+ var len = 0;
9228
+ for (var key in this.obj) {
9229
+ if (hasOwnProperty.call(this.obj, key)) {
9230
+ ++len;
9231
+ }
9232
+ }
9233
+ return (this.hasProto ? len + 1 : len);
9234
+ };
9235
+
9236
+ stringmap.prototype.keys = function() {
9237
+ var keys = [];
9238
+ for (var key in this.obj) {
9239
+ if (hasOwnProperty.call(this.obj, key)) {
9240
+ keys.push(key);
9241
+ }
9242
+ }
9243
+ if (this.hasProto) {
9244
+ keys.push("__proto__");
9245
+ }
9246
+ return keys;
9247
+ };
9248
+
9249
+ stringmap.prototype.values = function() {
9250
+ var values = [];
9251
+ for (var key in this.obj) {
9252
+ if (hasOwnProperty.call(this.obj, key)) {
9253
+ values.push(this.obj[key]);
9254
+ }
9255
+ }
9256
+ if (this.hasProto) {
9257
+ values.push(this.proto);
9258
+ }
9259
+ return values;
9260
+ };
9261
+
9262
+ stringmap.prototype.items = function() {
9263
+ var items = [];
9264
+ for (var key in this.obj) {
9265
+ if (hasOwnProperty.call(this.obj, key)) {
9266
+ items.push([key, this.obj[key]]);
9267
+ }
9268
+ }
9269
+ if (this.hasProto) {
9270
+ items.push(["__proto__", this.proto]);
9271
+ }
9272
+ return items;
9273
+ };
9274
+
9275
+
9276
+ // methods that rely on the above primitives
9277
+ stringmap.prototype.setMany = function(object) {
9278
+ if (object === null || (typeof object !== "object" && typeof object !== "function")) {
9279
+ throw new Error("StringMap expected Object");
9280
+ }
9281
+ for (var key in object) {
9282
+ if (hasOwnProperty.call(object, key)) {
9283
+ this.set(key, object[key]);
9284
+ }
9285
+ }
9286
+ return this;
9287
+ };
9288
+
9289
+ stringmap.prototype.merge = function(other) {
9290
+ var keys = other.keys();
9291
+ for (var i = 0; i < keys.length; i++) {
9292
+ var key = keys[i];
9293
+ this.set(key, other.get(key));
9294
+ }
9295
+ return this;
9296
+ };
9297
+
9298
+ stringmap.prototype.map = function(fn) {
9299
+ var keys = this.keys();
9300
+ for (var i = 0; i < keys.length; i++) {
9301
+ var key = keys[i];
9302
+ keys[i] = fn(this.get(key), key); // re-use keys array for results
9303
+ }
9304
+ return keys;
9305
+ };
9306
+
9307
+ stringmap.prototype.forEach = function(fn) {
9308
+ var keys = this.keys();
9309
+ for (var i = 0; i < keys.length; i++) {
9310
+ var key = keys[i];
9311
+ fn(this.get(key), key);
9312
+ }
9313
+ };
9314
+
9315
+ stringmap.prototype.clone = function() {
9316
+ var other = stringmap();
9317
+ return other.merge(this);
9318
+ };
9319
+
9320
+ stringmap.prototype.toString = function() {
9321
+ var self = this;
9322
+ return "{" + this.keys().map(function(key) {
9323
+ return JSON.stringify(key) + ":" + JSON.stringify(self.get(key));
9324
+ }).join(",") + "}";
9325
+ };
9326
+
9327
+ return stringmap;
9328
+ })();
9329
+
9330
+ if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
9331
+ module.exports = StringMap;
9332
+ }
9333
+
9334
+ },{}],32:[function(require,module,exports){
9335
+ // stringset.js
9336
+ // MIT licensed, see LICENSE file
9337
+ // Copyright (c) 2013 Olov Lassus <olov.lassus@gmail.com>
9338
+
9339
+ var StringSet = (function() {
9340
+ "use strict";
9341
+
9342
+ // to save us a few characters
9343
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
9344
+
9345
+ var create = (function() {
9346
+ function hasOwnEnumerableProps(obj) {
9347
+ for (var prop in obj) {
9348
+ if (hasOwnProperty.call(obj, prop)) {
9349
+ return true;
9350
+ }
9351
+ }
9352
+ return false;
9353
+ }
9354
+
9355
+ // FF <= 3.6:
9356
+ // o = {}; o.hasOwnProperty("__proto__" or "__count__" or "__parent__") => true
9357
+ // o = {"__proto__": null}; Object.prototype.hasOwnProperty.call(o, "__proto__" or "__count__" or "__parent__") => false
9358
+ function hasOwnPollutedProps(obj) {
9359
+ return hasOwnProperty.call(obj, "__count__") || hasOwnProperty.call(obj, "__parent__");
9360
+ }
9361
+
9362
+ var useObjectCreate = false;
9363
+ if (typeof Object.create === "function") {
9364
+ if (!hasOwnEnumerableProps(Object.create(null))) {
9365
+ useObjectCreate = true;
9366
+ }
9367
+ }
9368
+ if (useObjectCreate === false) {
9369
+ if (hasOwnEnumerableProps({})) {
9370
+ throw new Error("StringSet environment error 0, please file a bug at https://github.com/olov/stringset/issues");
9371
+ }
9372
+ }
9373
+ // no throw yet means we can create objects without own enumerable props (safe-guard against VMs and shims)
9374
+
9375
+ var o = (useObjectCreate ? Object.create(null) : {});
9376
+ var useProtoClear = false;
9377
+ if (hasOwnPollutedProps(o)) {
9378
+ o.__proto__ = null;
9379
+ if (hasOwnEnumerableProps(o) || hasOwnPollutedProps(o)) {
9380
+ throw new Error("StringSet environment error 1, please file a bug at https://github.com/olov/stringset/issues");
9381
+ }
9382
+ useProtoClear = true;
9383
+ }
9384
+ // no throw yet means we can create objects without own polluted props (safe-guard against VMs and shims)
9385
+
9386
+ return function() {
9387
+ var o = (useObjectCreate ? Object.create(null) : {});
9388
+ if (useProtoClear) {
9389
+ o.__proto__ = null;
9390
+ }
9391
+ return o;
9392
+ };
9393
+ })();
9394
+
9395
+ // stringset ctor
9396
+ function stringset(optional_array) {
9397
+ // use with or without new
9398
+ if (!(this instanceof stringset)) {
9399
+ return new stringset(optional_array);
9400
+ }
9401
+ this.obj = create();
9402
+ this.hasProto = false; // false (no __proto__ item) or true (has __proto__ item)
9403
+
9404
+ if (optional_array) {
9405
+ this.addMany(optional_array);
9406
+ }
9407
+ };
9408
+
9409
+ // primitive methods that deals with data representation
9410
+ stringset.prototype.has = function(item) {
9411
+ // The type-check of item in has, get, set and delete is important because otherwise an object
9412
+ // {toString: function() { return "__proto__"; }} can avoid the item === "__proto__" test.
9413
+ // The alternative to type-checking would be to force string conversion, i.e. item = String(item);
9414
+ if (typeof item !== "string") {
9415
+ throw new Error("StringSet expected string item");
9416
+ }
9417
+ return (item === "__proto__" ?
9418
+ this.hasProto :
9419
+ hasOwnProperty.call(this.obj, item));
9420
+ };
9421
+
9422
+ stringset.prototype.add = function(item) {
9423
+ if (typeof item !== "string") {
9424
+ throw new Error("StringSet expected string item");
9425
+ }
9426
+ if (item === "__proto__") {
9427
+ this.hasProto = true;
9428
+ } else {
9429
+ this.obj[item] = true;
9430
+ }
9431
+ };
9432
+
9433
+ stringset.prototype.remove = function(item) {
9434
+ if (typeof item !== "string") {
9435
+ throw new Error("StringSet expected string item");
9436
+ }
9437
+ var didExist = this.has(item);
9438
+ if (item === "__proto__") {
9439
+ this.hasProto = false;
9440
+ } else {
9441
+ delete this.obj[item];
9442
+ }
9443
+ return didExist;
9444
+ };
9445
+
9446
+ // alias remove to delete but beware:
9447
+ // ss.delete("key"); // OK in ES5 and later
9448
+ // ss['delete']("key"); // OK in all ES versions
9449
+ // ss.remove("key"); // OK in all ES versions
9450
+ stringset.prototype['delete'] = stringset.prototype.remove;
9451
+
9452
+ stringset.prototype.isEmpty = function() {
9453
+ for (var item in this.obj) {
9454
+ if (hasOwnProperty.call(this.obj, item)) {
9455
+ return false;
9456
+ }
9457
+ }
9458
+ return !this.hasProto;
9459
+ };
9460
+
9461
+ stringset.prototype.size = function() {
9462
+ var len = 0;
9463
+ for (var item in this.obj) {
9464
+ if (hasOwnProperty.call(this.obj, item)) {
9465
+ ++len;
9466
+ }
9467
+ }
9468
+ return (this.hasProto ? len + 1 : len);
9469
+ };
9470
+
9471
+ stringset.prototype.items = function() {
9472
+ var items = [];
9473
+ for (var item in this.obj) {
9474
+ if (hasOwnProperty.call(this.obj, item)) {
9475
+ items.push(item);
9476
+ }
9477
+ }
9478
+ if (this.hasProto) {
9479
+ items.push("__proto__");
9480
+ }
9481
+ return items;
9482
+ };
9483
+
9484
+
9485
+ // methods that rely on the above primitives
9486
+ stringset.prototype.addMany = function(items) {
9487
+ if (!Array.isArray(items)) {
9488
+ throw new Error("StringSet expected array");
9489
+ }
9490
+ for (var i = 0; i < items.length; i++) {
9491
+ this.add(items[i]);
9492
+ }
9493
+ return this;
9494
+ };
9495
+
9496
+ stringset.prototype.merge = function(other) {
9497
+ this.addMany(other.items());
9498
+ return this;
9499
+ };
9500
+
9501
+ stringset.prototype.clone = function() {
9502
+ var other = stringset();
9503
+ return other.merge(this);
9504
+ };
9505
+
9506
+ stringset.prototype.toString = function() {
9507
+ return "{" + this.items().map(JSON.stringify).join(",") + "}";
9508
+ };
9509
+
9510
+ return stringset;
9511
+ })();
9512
+
9513
+ if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
9514
+ module.exports = StringSet;
9515
+ }
9516
+
8750
9517
  },{}]},{},[10]);