ngannotate-rails 0.9.9 → 0.9.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/lib/ngannotate/rails/version.rb +1 -1
- data/vendor/ngannotate.js +1074 -307
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MWE4NWU5NzAyODRkODQ3ZTE3Y2Q1NWM1ODBkMmIyYzkyZmYzMGY2MA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MWY2ZGNlZTEzZmUwYmZiYzA5MmMzYzIzOGVkMzBkNWVmZWY3NzA3OQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
N2I1NzE3YzQ2M2FmOGM4NjU4NDViZmQyYzMwZGQ3NDU4OTRlNmM1YTAxNTFk
|
10
|
+
MGM4MDRmOTBjZDQ1Zjc0M2I3OWI3NWRhYjRhZTU3NzRjMzI5ZTdhZjAzODg2
|
11
|
+
YmRjMTRlMDBmMTc3ZWI3YmFjMTIzOTMxYzJkNzcyZjU4ZjkyMmY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZDJkMGNjYTBkNjJlY2EyYWNhMmJhNzI2Y2UzNmZhZDQ1NjIzMGQzZjk3Yjli
|
14
|
+
ODNiNjQxYzNlZGQxZTUwY2MzNDEzZDY1MjIyMjQ0OWM2ZDg1NmM1MDc3NWE3
|
15
|
+
Y2YyMDkzZjJlOWFiNDE1NGRjN2IxN2Y1ZDlhZTU2NzVlOTQ4OTI=
|
data/vendor/ngannotate.js
CHANGED
@@ -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":
|
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
|
1425
|
+
var traverse = require("ordered-ast-traverse");
|
1426
|
+
var is = require("simple-is");
|
1422
1427
|
|
1423
|
-
|
1424
|
-
assert(this instanceof Heap);
|
1428
|
+
module.exports = Lut;
|
1425
1429
|
|
1426
|
-
|
1427
|
-
|
1428
|
-
});
|
1430
|
+
function Lut(ast, src) {
|
1431
|
+
assert(this instanceof Lut);
|
1429
1432
|
|
1430
|
-
|
1431
|
-
|
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
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
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
|
-
|
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
|
-
|
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
|
1467
|
-
var
|
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
|
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
|
-
|
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,"./
|
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
|
-
|
2223
|
+
inspectComments: inspectComments,
|
2224
|
+
inspectCallExpression: inspectCallExpression,
|
2007
2225
|
};
|
2008
2226
|
|
2009
|
-
function
|
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
|
2016
|
-
|
2017
|
-
|
2018
|
-
|
2019
|
-
|
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
|
-
|
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
|
2043
|
-
|
2044
|
-
|
2045
|
-
|
2046
|
-
|
2047
|
-
|
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
|
-
|
2051
|
-
|
2052
|
-
|
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
|
-
|
2058
|
-
|
2059
|
-
|
2060
|
-
|
2061
|
-
if (
|
2062
|
-
(
|
2063
|
-
|
2064
|
-
|
2065
|
-
|
2066
|
-
|
2067
|
-
|
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
|
-
|
2075
|
-
|
2076
|
-
|
2077
|
-
|
2078
|
-
|
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
|
-
|
2084
|
-
|
2085
|
-
|
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
|
-
|
2088
|
-
|
2089
|
-
|
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
|
-
|
2093
|
-
|
2094
|
-
|
2095
|
-
var
|
2096
|
-
|
2097
|
-
|
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
|
-
|
2101
|
-
|
2102
|
-
|
2103
|
-
|
2104
|
-
|
2105
|
-
|
2106
|
-
|
2107
|
-
|
2108
|
-
|
2109
|
-
|
2110
|
-
|
2111
|
-
|
2112
|
-
|
2113
|
-
|
2114
|
-
|
2115
|
-
|
2116
|
-
|
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
|
-
|
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":
|
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
|
-
},{}],
|
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
|
-
},{}],
|
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":
|
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
|
-
},{}],
|
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
|
-
},{}],
|
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":
|
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":
|
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":
|
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":
|
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":
|
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":
|
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":
|
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":
|
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":
|
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}],
|
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]);
|