ngannotate-rails 0.10.1 → 0.12.1
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 +5 -13
- data/.ruby-version +1 -1
- data/lib/ngannotate/rails/version.rb +1 -1
- data/vendor/ngannotate.js +3017 -277
- metadata +16 -16
checksums.yaml
CHANGED
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
|
|
5
|
-
data.tar.gz: !binary |-
|
|
6
|
-
MWMwZjQzNzkyMWY5YjRlOTYxY2Y2MzI5MDM0MWZjMDA2MWU0NGY1Mw==
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 6eb1737fcf0afa5ea00f1e82a330c7ab64770225
|
|
4
|
+
data.tar.gz: fcfe26fd09d2ac827928d8474dc75dc89b4b6f44
|
|
7
5
|
SHA512:
|
|
8
|
-
metadata.gz:
|
|
9
|
-
|
|
10
|
-
MTczMTU2NDRiZWI3MzRjOWM1ZTY0MTQxMWM1NTAwYWY1MjViZTZhODFiYWRi
|
|
11
|
-
MmM2M2MzNWE2YWVlYzc0NDVhYTczMzY4ZGVlNjlmZDc5NDY5MzY=
|
|
12
|
-
data.tar.gz: !binary |-
|
|
13
|
-
N2Y4YTA4NGY5MzM4MmU3MDk4ZjBkMjUzZDFmNWU2YTc5NDkyZmUxMGFhMGM4
|
|
14
|
-
YTQ0MjMxMmFlZDQ3NDAwNDhiMjQ5ODhhNzBjOTY0MzY5ZDMzM2Q3ODgyODUx
|
|
15
|
-
YWZmMTBmMDE3ODM1MWJmNzNmZjI1ODY0MzQ0NjZjOThjMjE5ZWY=
|
|
6
|
+
metadata.gz: 732565bc3e8b91bf37ef22829345cb1c1543ae7cdca342dcd3983d696d17947728cbeddaf71a82b8e84cc5fbce1a9ffb38c5526c08bd19a304ae511718e69d25
|
|
7
|
+
data.tar.gz: 136e610aaa587d154244d5ec10d40398081d34d1e1988c4a7ed89ef611c25a327ad7bbc7fae44c2ba9cd2e50830bf831a2aea407e1bbd4f82d825d497027336a
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby-1.
|
|
1
|
+
ruby-2.1.5
|
data/vendor/ngannotate.js
CHANGED
|
@@ -668,6 +668,8 @@ var process = module.exports = {};
|
|
|
668
668
|
process.nextTick = (function () {
|
|
669
669
|
var canSetImmediate = typeof window !== 'undefined'
|
|
670
670
|
&& window.setImmediate;
|
|
671
|
+
var canMutationObserver = typeof window !== 'undefined'
|
|
672
|
+
&& window.MutationObserver;
|
|
671
673
|
var canPost = typeof window !== 'undefined'
|
|
672
674
|
&& window.postMessage && window.addEventListener
|
|
673
675
|
;
|
|
@@ -676,8 +678,29 @@ process.nextTick = (function () {
|
|
|
676
678
|
return function (f) { return window.setImmediate(f) };
|
|
677
679
|
}
|
|
678
680
|
|
|
681
|
+
var queue = [];
|
|
682
|
+
|
|
683
|
+
if (canMutationObserver) {
|
|
684
|
+
var hiddenDiv = document.createElement("div");
|
|
685
|
+
var observer = new MutationObserver(function () {
|
|
686
|
+
var queueList = queue.slice();
|
|
687
|
+
queue.length = 0;
|
|
688
|
+
queueList.forEach(function (fn) {
|
|
689
|
+
fn();
|
|
690
|
+
});
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
observer.observe(hiddenDiv, { attributes: true });
|
|
694
|
+
|
|
695
|
+
return function nextTick(fn) {
|
|
696
|
+
if (!queue.length) {
|
|
697
|
+
hiddenDiv.setAttribute('yes', 'no');
|
|
698
|
+
}
|
|
699
|
+
queue.push(fn);
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
|
|
679
703
|
if (canPost) {
|
|
680
|
-
var queue = [];
|
|
681
704
|
window.addEventListener('message', function (ev) {
|
|
682
705
|
var source = ev.source;
|
|
683
706
|
if ((source === window || source === null) && ev.data === 'process-tick') {
|
|
@@ -717,7 +740,7 @@ process.emit = noop;
|
|
|
717
740
|
|
|
718
741
|
process.binding = function (name) {
|
|
719
742
|
throw new Error('process.binding is not supported');
|
|
720
|
-
}
|
|
743
|
+
};
|
|
721
744
|
|
|
722
745
|
// TODO(shtylman)
|
|
723
746
|
process.cwd = function () { return '/' };
|
|
@@ -1414,7 +1437,7 @@ module.exports = function generateSourcemap(src, fragments, inFile, sourceRoot)
|
|
|
1414
1437
|
return new SourceMapper(src, fragments, inFile, sourceRoot).generate();
|
|
1415
1438
|
}
|
|
1416
1439
|
|
|
1417
|
-
},{"source-map":
|
|
1440
|
+
},{"source-map":21,"stable":31}],9:[function(require,module,exports){
|
|
1418
1441
|
// lut.js
|
|
1419
1442
|
// MIT licensed, see LICENSE file
|
|
1420
1443
|
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
|
|
@@ -1542,15 +1565,12 @@ function last(arr) {
|
|
|
1542
1565
|
return arr[arr.length - 1];
|
|
1543
1566
|
}
|
|
1544
1567
|
|
|
1545
|
-
},{"assert":1,"ordered-ast-traverse":
|
|
1568
|
+
},{"assert":1,"ordered-ast-traverse":18,"simple-is":20}],10:[function(require,module,exports){
|
|
1546
1569
|
// ng-annotate-main.js
|
|
1547
1570
|
// MIT licensed, see LICENSE file
|
|
1548
1571
|
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
|
|
1549
1572
|
|
|
1550
1573
|
"use strict";
|
|
1551
|
-
var esprima_require_t0 = Date.now();
|
|
1552
|
-
var esprima = require("esprima").parse;
|
|
1553
|
-
var esprima_require_t1 = Date.now();
|
|
1554
1574
|
var fmt = require("simple-fmt");
|
|
1555
1575
|
var is = require("simple-is");
|
|
1556
1576
|
var alter = require("alter");
|
|
@@ -1562,6 +1582,7 @@ var generateSourcemap = require("./generate-sourcemap");
|
|
|
1562
1582
|
var Lut = require("./lut");
|
|
1563
1583
|
var scopeTools = require("./scopetools");
|
|
1564
1584
|
var stringmap = require("stringmap");
|
|
1585
|
+
var parser = null; // will be lazy-loaded to esprima or acorn
|
|
1565
1586
|
|
|
1566
1587
|
var chainedRouteProvider = 1;
|
|
1567
1588
|
var chainedUrlRouterProvider = 2;
|
|
@@ -1575,8 +1596,10 @@ function match(node, ctx, matchPlugins) {
|
|
|
1575
1596
|
node.callee.computed === false
|
|
1576
1597
|
);
|
|
1577
1598
|
|
|
1599
|
+
// matchInjectorInvoke must happen before matchRegular
|
|
1600
|
+
// to prevent false positive ($injector.invoke() outside module)
|
|
1578
1601
|
var matchMethodCalls = (isMethodCall &&
|
|
1579
|
-
(matchRegular(node, ctx) || matchNgRoute(node) || matchNgUi(node) || matchHttpProvider(node)));
|
|
1602
|
+
(matchInjectorInvoke(node) || matchRegular(node, ctx) || matchNgRoute(node) || matchNgUi(node) || matchHttpProvider(node)));
|
|
1580
1603
|
|
|
1581
1604
|
return matchMethodCalls ||
|
|
1582
1605
|
(matchPlugins && matchPlugins(node)) ||
|
|
@@ -1769,6 +1792,19 @@ function matchNgUi(node) {
|
|
|
1769
1792
|
}
|
|
1770
1793
|
}
|
|
1771
1794
|
|
|
1795
|
+
function matchInjectorInvoke(node) {
|
|
1796
|
+
// $injector.invoke(function($compile) { ... });
|
|
1797
|
+
|
|
1798
|
+
// we already know that node is a (non-computed) method call
|
|
1799
|
+
var callee = node.callee;
|
|
1800
|
+
var obj = callee.object; // identifier or expression
|
|
1801
|
+
var method = callee.property; // identifier
|
|
1802
|
+
|
|
1803
|
+
return method.name === "invoke" &&
|
|
1804
|
+
obj.type === "Identifier" && obj.name === "$injector" &&
|
|
1805
|
+
node.arguments.length >= 1 && node.arguments;
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1772
1808
|
function matchHttpProvider(node) {
|
|
1773
1809
|
// $httpProvider.interceptors.push(function($scope) {});
|
|
1774
1810
|
// $httpProvider.responseInterceptors.push(function($scope) {});
|
|
@@ -1849,7 +1885,8 @@ function last(arr) {
|
|
|
1849
1885
|
function matchProp(name, props) {
|
|
1850
1886
|
for (var i = 0; i < props.length; i++) {
|
|
1851
1887
|
var prop = props[i];
|
|
1852
|
-
if (prop.key.type === "Identifier" && prop.key.name === name)
|
|
1888
|
+
if ((prop.key.type === "Identifier" && prop.key.name === name) ||
|
|
1889
|
+
(prop.key.type === "Literal" && prop.key.value === name)) {
|
|
1853
1890
|
return prop.value; // FunctionExpression or ArrayExpression
|
|
1854
1891
|
}
|
|
1855
1892
|
}
|
|
@@ -1879,10 +1916,59 @@ function stringify(ctx, arr, quot) {
|
|
|
1879
1916
|
}).join(", ") + "]";
|
|
1880
1917
|
}
|
|
1881
1918
|
|
|
1919
|
+
function parseExpressionOfType(str, type) {
|
|
1920
|
+
var node = parser(str).body[0].expression;
|
|
1921
|
+
assert(node.type === type);
|
|
1922
|
+
return node;
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
// stand-in for not having a jsshaper-style ref's
|
|
1926
|
+
function replaceNodeWith(node, newNode) {
|
|
1927
|
+
var done = false;
|
|
1928
|
+
var parent = node.$parent;
|
|
1929
|
+
var keys = Object.keys(parent);
|
|
1930
|
+
keys.forEach(function(key) {
|
|
1931
|
+
if (parent[key] === node) {
|
|
1932
|
+
parent[key] = newNode;
|
|
1933
|
+
done = true;
|
|
1934
|
+
}
|
|
1935
|
+
});
|
|
1936
|
+
|
|
1937
|
+
if (done) {
|
|
1938
|
+
return;
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
// second pass, now check arrays
|
|
1942
|
+
keys.forEach(function(key) {
|
|
1943
|
+
if (Array.isArray(parent[key])) {
|
|
1944
|
+
var arr = parent[key];
|
|
1945
|
+
for (var i = 0; i < arr.length; i++) {
|
|
1946
|
+
if (arr[i] === node) {
|
|
1947
|
+
arr[i] = newNode;
|
|
1948
|
+
done = true;
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
});
|
|
1953
|
+
|
|
1954
|
+
assert(done);
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1882
1957
|
function insertArray(ctx, functionExpression, fragments, quot) {
|
|
1883
1958
|
var range = functionExpression.range;
|
|
1884
1959
|
|
|
1885
1960
|
var args = stringify(ctx, functionExpression.params, quot);
|
|
1961
|
+
|
|
1962
|
+
// modify the AST
|
|
1963
|
+
/*
|
|
1964
|
+
const arrayExpression = parseExpressionOfType(args, "ArrayExpression");
|
|
1965
|
+
const parent = functionExpression.$parent;
|
|
1966
|
+
replaceNodeWith(functionExpression, arrayExpression);
|
|
1967
|
+
arrayExpression.$parent = parent;
|
|
1968
|
+
arrayExpression.elements.push(functionExpression)
|
|
1969
|
+
functionExpression.$parent = arrayExpression;
|
|
1970
|
+
*/
|
|
1971
|
+
|
|
1886
1972
|
fragments.push({
|
|
1887
1973
|
start: range[0],
|
|
1888
1974
|
end: range[0],
|
|
@@ -2066,9 +2152,15 @@ function followReference(node) {
|
|
|
2066
2152
|
|
|
2067
2153
|
if (is.someof(kind, ["const", "let", "var"])) {
|
|
2068
2154
|
assert(ptype === "VariableDeclarator");
|
|
2069
|
-
|
|
2155
|
+
// {type: "VariableDeclarator", id: {type: "Identifier", name: "foo"}, init: ..}
|
|
2156
|
+
return parent;
|
|
2070
2157
|
} else if (kind === "fun") {
|
|
2071
2158
|
assert(ptype === "FunctionDeclaration" || ptype === "FunctionExpression")
|
|
2159
|
+
// FunctionDeclaration is the common case, i.e.
|
|
2160
|
+
// function foo(a, b) {}
|
|
2161
|
+
|
|
2162
|
+
// FunctionExpression is only applicable for cases similar to
|
|
2163
|
+
// var f = function asdf(a,b) { mymod.controller("asdf", asdf) };
|
|
2072
2164
|
return parent;
|
|
2073
2165
|
}
|
|
2074
2166
|
|
|
@@ -2098,31 +2190,72 @@ function posToLine(pos, src) {
|
|
|
2098
2190
|
}
|
|
2099
2191
|
|
|
2100
2192
|
function judgeInjectArraySuspect(node, ctx) {
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2193
|
+
if (node.type === "VariableDeclaration") {
|
|
2194
|
+
// suspect can only be a VariableDeclaration (statement) in case of
|
|
2195
|
+
// explicitly marked via ngInject, not via references because
|
|
2196
|
+
// references follow to VariableDeclarator (child)
|
|
2197
|
+
|
|
2198
|
+
// /*@ngInject*/ var foo = function($scope) {} and
|
|
2199
|
+
|
|
2200
|
+
if (node.declarations.length !== 1) {
|
|
2201
|
+
// more than one declarator => exit
|
|
2202
|
+
return;
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
// one declarator => jump over declaration into declarator
|
|
2206
|
+
// rest of code will treat it as any (referenced) declarator
|
|
2207
|
+
node = node.declarations[0];
|
|
2208
|
+
}
|
|
2209
|
+
|
|
2210
|
+
// onode is a top-level node (inside function block), later verified
|
|
2211
|
+
// node is inner match, descent in multiple steps
|
|
2212
|
+
var onode = null;
|
|
2213
|
+
var declaratorName = null;
|
|
2214
|
+
if (node.type === "VariableDeclarator") {
|
|
2215
|
+
onode = node.$parent;
|
|
2216
|
+
declaratorName = node.id.name;
|
|
2217
|
+
node = node.init; // var foo = ___;
|
|
2218
|
+
} else {
|
|
2219
|
+
onode = node;
|
|
2220
|
+
}
|
|
2104
2221
|
|
|
2105
2222
|
// suspect must be inside of a block or at the top-level (i.e. inside of node.$parent.body[])
|
|
2106
|
-
if (!node.$parent || is.noneof(
|
|
2223
|
+
if (!node || !onode.$parent || is.noneof(onode.$parent.type, ["Program", "BlockStatement"])) {
|
|
2107
2224
|
return;
|
|
2108
2225
|
}
|
|
2109
2226
|
|
|
2110
|
-
var
|
|
2111
|
-
var
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2227
|
+
var insertPos = onode.range[1];
|
|
2228
|
+
var isSemicolonTerminated = (ctx.src[insertPos - 1] === ";");
|
|
2229
|
+
|
|
2230
|
+
node = jumpOverIife(node);
|
|
2231
|
+
|
|
2232
|
+
if (ctx.isFunctionExpressionWithArgs(node)) {
|
|
2233
|
+
// var x = 1, y = function(a,b) {}, z;
|
|
2234
|
+
|
|
2235
|
+
assert(declaratorName);
|
|
2236
|
+
addRemoveInjectArray(node.params, isSemicolonTerminated ? insertPos : node.range[1], declaratorName);
|
|
2237
|
+
|
|
2117
2238
|
} else if (ctx.isFunctionDeclarationWithArgs(node)) {
|
|
2118
|
-
|
|
2239
|
+
// /*@ngInject*/ function foo($scope) {}
|
|
2240
|
+
|
|
2241
|
+
addRemoveInjectArray(node.params, insertPos, node.id.name);
|
|
2242
|
+
|
|
2119
2243
|
} else if (node.type === "ExpressionStatement" && node.expression.type === "AssignmentExpression" &&
|
|
2120
2244
|
ctx.isFunctionExpressionWithArgs(node.expression.right)) {
|
|
2121
|
-
|
|
2245
|
+
// /*@ngInject*/ foo.bar[0] = function($scope) {}
|
|
2246
|
+
|
|
2122
2247
|
var name = ctx.srcForRange(node.expression.left.range);
|
|
2123
|
-
addRemoveInjectArray(node.expression.right.params,
|
|
2248
|
+
addRemoveInjectArray(node.expression.right.params, isSemicolonTerminated ? insertPos : node.expression.right.range[1], name);
|
|
2249
|
+
|
|
2250
|
+
} else if (node = followReference(node)) {
|
|
2251
|
+
// node was a reference and followed node now is either a
|
|
2252
|
+
// FunctionDeclaration or a VariableDeclarator
|
|
2253
|
+
// => recurse
|
|
2254
|
+
|
|
2255
|
+
judgeInjectArraySuspect(node, ctx);
|
|
2124
2256
|
}
|
|
2125
2257
|
|
|
2258
|
+
|
|
2126
2259
|
function getIndent(pos) {
|
|
2127
2260
|
var src = ctx.src;
|
|
2128
2261
|
var lineStart = src.lastIndexOf("\n", pos - 1) + 1;
|
|
@@ -2132,7 +2265,7 @@ function judgeInjectArraySuspect(node, ctx) {
|
|
|
2132
2265
|
return src.slice(lineStart, i);
|
|
2133
2266
|
}
|
|
2134
2267
|
|
|
2135
|
-
function addRemoveInjectArray(params,
|
|
2268
|
+
function addRemoveInjectArray(params, posAfterFunctionDeclaration, name) {
|
|
2136
2269
|
// if an existing something.$inject = [..] exists then is will always be recycled when rebuilding
|
|
2137
2270
|
|
|
2138
2271
|
var indent = getIndent(posAfterFunctionDeclaration);
|
|
@@ -2140,8 +2273,8 @@ function judgeInjectArraySuspect(node, ctx) {
|
|
|
2140
2273
|
var foundSuspectInBody = false;
|
|
2141
2274
|
var existingExpressionStatementWithArray = null;
|
|
2142
2275
|
var troublesomeReturn = false;
|
|
2143
|
-
|
|
2144
|
-
if (bnode ===
|
|
2276
|
+
onode.$parent.body.forEach(function(bnode) {
|
|
2277
|
+
if (bnode === onode) {
|
|
2145
2278
|
foundSuspectInBody = true;
|
|
2146
2279
|
}
|
|
2147
2280
|
|
|
@@ -2175,15 +2308,6 @@ function judgeInjectArraySuspect(node, ctx) {
|
|
|
2175
2308
|
(lvalue.computed === true && ctx.srcForRange(lvalue.object.range) === name && lvalue.property.type === "Literal" && lvalue.property.value === "$inject")));
|
|
2176
2309
|
}
|
|
2177
2310
|
|
|
2178
|
-
function skipNewline(pos) {
|
|
2179
|
-
if (ctx.src[pos] === "\n") {
|
|
2180
|
-
return pos + 1;
|
|
2181
|
-
} else if (ctx.src.slice(pos, pos + 2) === "\r\n") {
|
|
2182
|
-
return pos + 2;
|
|
2183
|
-
}
|
|
2184
|
-
return pos;
|
|
2185
|
-
}
|
|
2186
|
-
|
|
2187
2311
|
function skipPrevNewline(pos) {
|
|
2188
2312
|
var prevLF = ctx.src.lastIndexOf("\n", pos);
|
|
2189
2313
|
if (prevLF === -1) {
|
|
@@ -2226,13 +2350,18 @@ function judgeInjectArraySuspect(node, ctx) {
|
|
|
2226
2350
|
|
|
2227
2351
|
function jumpOverIife(node) {
|
|
2228
2352
|
var outerfn;
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2353
|
+
if (!(node.type === "CallExpression" && (outerfn = node.callee).type === "FunctionExpression")) {
|
|
2354
|
+
return node;
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
var outerbody = outerfn.body.body;
|
|
2358
|
+
for (var i = 0; i < outerbody.length; i++) {
|
|
2359
|
+
var statement = outerbody[i];
|
|
2360
|
+
if (statement.type === "ReturnStatement") {
|
|
2361
|
+
return statement.argument;
|
|
2362
|
+
}
|
|
2235
2363
|
}
|
|
2364
|
+
|
|
2236
2365
|
return node;
|
|
2237
2366
|
}
|
|
2238
2367
|
|
|
@@ -2277,37 +2406,58 @@ window.annotate = function ngAnnotate(src, options) {
|
|
|
2277
2406
|
}
|
|
2278
2407
|
var ast;
|
|
2279
2408
|
var stats = {};
|
|
2409
|
+
|
|
2410
|
+
// [{type: "Block"|"Line", value: str, range: [from,to]}, ..]
|
|
2411
|
+
var comments = [];
|
|
2412
|
+
|
|
2413
|
+
stats.parser_require_t0 = Date.now();
|
|
2414
|
+
if (!options.es6) {
|
|
2415
|
+
parser = require("esprima").parse;
|
|
2416
|
+
} else {
|
|
2417
|
+
parser = require("acorn").parse;
|
|
2418
|
+
}
|
|
2419
|
+
stats.parser_require_t1 = Date.now();
|
|
2420
|
+
|
|
2280
2421
|
try {
|
|
2281
|
-
stats.
|
|
2282
|
-
stats.esprima_require_t1 = esprima_require_t1;
|
|
2283
|
-
stats.esprima_parse_t0 = Date.now();
|
|
2422
|
+
stats.parser_parse_t0 = Date.now();
|
|
2284
2423
|
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2424
|
+
if (!options.es6) {
|
|
2425
|
+
// esprima
|
|
2426
|
+
ast = parser(src, {
|
|
2427
|
+
range: true,
|
|
2428
|
+
comment: true,
|
|
2429
|
+
});
|
|
2430
|
+
|
|
2431
|
+
// Fix Program node range (https://code.google.com/p/esprima/issues/detail?id=541)
|
|
2432
|
+
ast.range[0] = 0;
|
|
2433
|
+
|
|
2434
|
+
// detach comments from ast
|
|
2435
|
+
comments = ast.comments;
|
|
2436
|
+
ast.comments = null;
|
|
2437
|
+
|
|
2438
|
+
} else {
|
|
2439
|
+
// acorn
|
|
2440
|
+
ast = parser(src, {
|
|
2441
|
+
ecmaVersion: 6,
|
|
2442
|
+
locations: true,
|
|
2443
|
+
ranges: true,
|
|
2444
|
+
onComment: comments,
|
|
2445
|
+
});
|
|
2446
|
+
}
|
|
2289
2447
|
|
|
2290
|
-
stats.
|
|
2448
|
+
stats.parser_parse_t1 = Date.now();
|
|
2291
2449
|
} catch(e) {
|
|
2292
2450
|
return {
|
|
2293
2451
|
errors: ["error: couldn't process source due to parse error", e.message],
|
|
2294
2452
|
};
|
|
2295
2453
|
}
|
|
2296
2454
|
|
|
2297
|
-
// Fix Program node range (https://code.google.com/p/esprima/issues/detail?id=541)
|
|
2298
|
-
ast.range[0] = 0;
|
|
2299
|
-
|
|
2300
2455
|
// append a dummy-node to ast so that lut.findNodeFromPos(lastPos) returns something
|
|
2301
2456
|
ast.body.push({
|
|
2302
2457
|
type: "DebuggerStatement",
|
|
2303
2458
|
range: [ast.range[1], ast.range[1]],
|
|
2304
2459
|
});
|
|
2305
2460
|
|
|
2306
|
-
// detach comments from ast
|
|
2307
|
-
// [{type: "Block"|"Line", value: str, range: [from,to]}, ..]
|
|
2308
|
-
var comments = ast.comments;
|
|
2309
|
-
ast.comments = null;
|
|
2310
|
-
|
|
2311
2461
|
// all source modifications are built up as operations in the
|
|
2312
2462
|
// fragments array, later sent to alter in one shot
|
|
2313
2463
|
var fragments = [];
|
|
@@ -2403,7 +2553,7 @@ window.annotate = function ngAnnotate(src, options) {
|
|
|
2403
2553
|
return result;
|
|
2404
2554
|
}
|
|
2405
2555
|
|
|
2406
|
-
},{"./generate-sourcemap":8,"./lut":9,"./nginject":11,"./scopetools":13,"
|
|
2556
|
+
},{"./generate-sourcemap":8,"./lut":9,"./nginject":11,"./scopetools":13,"acorn":14,"alter":15,"assert":1,"esprima":16,"ordered-ast-traverse":18,"os":3,"simple-fmt":19,"simple-is":20,"stringmap":32}],11:[function(require,module,exports){
|
|
2407
2557
|
// nginject-comments.js
|
|
2408
2558
|
// MIT licensed, see LICENSE file
|
|
2409
2559
|
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
|
|
@@ -2485,7 +2635,7 @@ function nestedObjectValues(node, res) {
|
|
|
2485
2635
|
return res;
|
|
2486
2636
|
}
|
|
2487
2637
|
|
|
2488
|
-
},{"simple-fmt":
|
|
2638
|
+
},{"simple-fmt":19,"simple-is":20}],12:[function(require,module,exports){
|
|
2489
2639
|
// scope.js
|
|
2490
2640
|
// MIT licensed, see LICENSE file
|
|
2491
2641
|
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
|
|
@@ -2608,226 +2758,2815 @@ Scope.prototype.getFromPos = function(name) {
|
|
|
2608
2758
|
return decl ? decl.from : null;
|
|
2609
2759
|
};
|
|
2610
2760
|
|
|
2611
|
-
Scope.prototype.hasOwn = function(name) {
|
|
2612
|
-
return this.decls.has(name);
|
|
2613
|
-
};
|
|
2761
|
+
Scope.prototype.hasOwn = function(name) {
|
|
2762
|
+
return this.decls.has(name);
|
|
2763
|
+
};
|
|
2764
|
+
|
|
2765
|
+
Scope.prototype.remove = function(name) {
|
|
2766
|
+
return this.decls.remove(name);
|
|
2767
|
+
};
|
|
2768
|
+
|
|
2769
|
+
Scope.prototype.doesPropagate = function(name) {
|
|
2770
|
+
return this.propagates.has(name);
|
|
2771
|
+
};
|
|
2772
|
+
|
|
2773
|
+
Scope.prototype.markPropagates = function(name) {
|
|
2774
|
+
this.propagates.add(name);
|
|
2775
|
+
};
|
|
2776
|
+
|
|
2777
|
+
Scope.prototype.closestHoistScope = function() {
|
|
2778
|
+
var scope = this;
|
|
2779
|
+
while (scope.kind !== "hoist") {
|
|
2780
|
+
scope = scope.parent;
|
|
2781
|
+
}
|
|
2782
|
+
return scope;
|
|
2783
|
+
};
|
|
2784
|
+
|
|
2785
|
+
Scope.prototype.lookup = function(name) {
|
|
2786
|
+
for (var scope = this; scope; scope = scope.parent) {
|
|
2787
|
+
if (scope.decls.has(name)) {
|
|
2788
|
+
return scope;
|
|
2789
|
+
} else if (scope.kind === "hoist") {
|
|
2790
|
+
scope.propagates.add(name);
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
return null;
|
|
2794
|
+
};
|
|
2795
|
+
|
|
2796
|
+
module.exports = Scope;
|
|
2797
|
+
|
|
2798
|
+
},{"assert":1,"simple-fmt":19,"simple-is":20,"stringmap":32,"stringset":33}],13:[function(require,module,exports){
|
|
2799
|
+
// scopetools.js
|
|
2800
|
+
// MIT licensed, see LICENSE file
|
|
2801
|
+
// Copyright (c) 2013-2014 Olov Lassus <olov.lassus@gmail.com>
|
|
2802
|
+
|
|
2803
|
+
"use strict";
|
|
2804
|
+
|
|
2805
|
+
var assert = require("assert");
|
|
2806
|
+
var traverse = require("ordered-ast-traverse");
|
|
2807
|
+
var Scope = require("./scope");
|
|
2808
|
+
var is = require("simple-is");
|
|
2809
|
+
|
|
2810
|
+
module.exports = {
|
|
2811
|
+
setupScopeAndReferences: setupScopeAndReferences,
|
|
2812
|
+
isReference: isReference,
|
|
2813
|
+
};
|
|
2814
|
+
|
|
2815
|
+
function setupScopeAndReferences(root) {
|
|
2816
|
+
traverse(root, {pre: createScopes});
|
|
2817
|
+
createTopScope(root.$scope);
|
|
2818
|
+
}
|
|
2819
|
+
|
|
2820
|
+
function createScopes(node, parent) {
|
|
2821
|
+
node.$parent = parent;
|
|
2822
|
+
node.$scope = parent ? parent.$scope : null; // may be overridden
|
|
2823
|
+
|
|
2824
|
+
if (isNonFunctionBlock(node, parent)) {
|
|
2825
|
+
// A block node is a scope unless parent is a function
|
|
2826
|
+
node.$scope = new Scope({
|
|
2827
|
+
kind: "block",
|
|
2828
|
+
node: node,
|
|
2829
|
+
parent: parent.$scope,
|
|
2830
|
+
});
|
|
2831
|
+
|
|
2832
|
+
} else if (node.type === "VariableDeclaration") {
|
|
2833
|
+
// Variable declarations names goes in current scope
|
|
2834
|
+
node.declarations.forEach(function(declarator) {
|
|
2835
|
+
var name = declarator.id.name;
|
|
2836
|
+
node.$scope.add(name, node.kind, declarator.id, declarator.range[1]);
|
|
2837
|
+
});
|
|
2838
|
+
|
|
2839
|
+
} else if (isFunction(node)) {
|
|
2840
|
+
// Function is a scope, with params in it
|
|
2841
|
+
// There's no block-scope under it
|
|
2842
|
+
|
|
2843
|
+
node.$scope = new Scope({
|
|
2844
|
+
kind: "hoist",
|
|
2845
|
+
node: node,
|
|
2846
|
+
parent: parent.$scope,
|
|
2847
|
+
});
|
|
2848
|
+
|
|
2849
|
+
// function has a name
|
|
2850
|
+
if (node.id) {
|
|
2851
|
+
if (node.type === "FunctionDeclaration") {
|
|
2852
|
+
// Function name goes in parent scope for declared functions
|
|
2853
|
+
parent.$scope.add(node.id.name, "fun", node.id, null);
|
|
2854
|
+
} else if (node.type === "FunctionExpression") {
|
|
2855
|
+
// Function name goes in function's scope for named function expressions
|
|
2856
|
+
node.$scope.add(node.id.name, "fun", node.id, null);
|
|
2857
|
+
} else {
|
|
2858
|
+
assert(false);
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
|
|
2862
|
+
node.params.forEach(function(param) {
|
|
2863
|
+
node.$scope.add(param.name, "param", param, null);
|
|
2864
|
+
});
|
|
2865
|
+
|
|
2866
|
+
} else if (isForWithConstLet(node) || isForInOfWithConstLet(node)) {
|
|
2867
|
+
// For(In/Of) loop with const|let declaration is a scope, with declaration in it
|
|
2868
|
+
// There may be a block-scope under it
|
|
2869
|
+
node.$scope = new Scope({
|
|
2870
|
+
kind: "block",
|
|
2871
|
+
node: node,
|
|
2872
|
+
parent: parent.$scope,
|
|
2873
|
+
});
|
|
2874
|
+
|
|
2875
|
+
} else if (node.type === "CatchClause") {
|
|
2876
|
+
var identifier = node.param;
|
|
2877
|
+
|
|
2878
|
+
node.$scope = new Scope({
|
|
2879
|
+
kind: "catch-block",
|
|
2880
|
+
node: node,
|
|
2881
|
+
parent: parent.$scope,
|
|
2882
|
+
});
|
|
2883
|
+
node.$scope.add(identifier.name, "caught", identifier, null);
|
|
2884
|
+
|
|
2885
|
+
// All hoist-scope keeps track of which variables that are propagated through,
|
|
2886
|
+
// i.e. an reference inside the scope points to a declaration outside the scope.
|
|
2887
|
+
// This is used to mark "taint" the name since adding a new variable in the scope,
|
|
2888
|
+
// with a propagated name, would change the meaning of the existing references.
|
|
2889
|
+
//
|
|
2890
|
+
// catch(e) is special because even though e is a variable in its own scope,
|
|
2891
|
+
// we want to make sure that catch(e){let e} is never transformed to
|
|
2892
|
+
// catch(e){var e} (but rather var e$0). For that reason we taint the use of e
|
|
2893
|
+
// in the closest hoist-scope, i.e. where var e$0 belongs.
|
|
2894
|
+
node.$scope.closestHoistScope().markPropagates(identifier.name);
|
|
2895
|
+
|
|
2896
|
+
} else if (node.type === "Program") {
|
|
2897
|
+
// Top-level program is a scope
|
|
2898
|
+
// There's no block-scope under it
|
|
2899
|
+
node.$scope = new Scope({
|
|
2900
|
+
kind: "hoist",
|
|
2901
|
+
node: node,
|
|
2902
|
+
parent: null,
|
|
2903
|
+
});
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
|
|
2907
|
+
function createTopScope(programScope) {
|
|
2908
|
+
function inject(obj) {
|
|
2909
|
+
for (var name in obj) {
|
|
2910
|
+
var writeable = obj[name];
|
|
2911
|
+
var kind = (writeable ? "var" : "const");
|
|
2912
|
+
if (topScope.hasOwn(name)) {
|
|
2913
|
+
topScope.remove(name);
|
|
2914
|
+
}
|
|
2915
|
+
topScope.add(name, kind, {loc: {start: {line: -1}}}, -1);
|
|
2916
|
+
}
|
|
2917
|
+
}
|
|
2918
|
+
|
|
2919
|
+
var topScope = new Scope({
|
|
2920
|
+
kind: "hoist",
|
|
2921
|
+
node: {},
|
|
2922
|
+
parent: null,
|
|
2923
|
+
});
|
|
2924
|
+
|
|
2925
|
+
var complementary = {
|
|
2926
|
+
undefined: false,
|
|
2927
|
+
Infinity: false,
|
|
2928
|
+
console: false,
|
|
2929
|
+
};
|
|
2930
|
+
|
|
2931
|
+
inject(complementary);
|
|
2932
|
+
// inject(jshint_vars.reservedVars);
|
|
2933
|
+
// inject(jshint_vars.ecmaIdentifiers);
|
|
2934
|
+
|
|
2935
|
+
// link it in
|
|
2936
|
+
programScope.parent = topScope;
|
|
2937
|
+
topScope.children.push(programScope);
|
|
2938
|
+
|
|
2939
|
+
return topScope;
|
|
2940
|
+
}
|
|
2941
|
+
|
|
2942
|
+
function isConstLet(kind) {
|
|
2943
|
+
return kind === "const" || kind === "let";
|
|
2944
|
+
}
|
|
2945
|
+
|
|
2946
|
+
function isNonFunctionBlock(node, parent) {
|
|
2947
|
+
return node.type === "BlockStatement" && parent.type !== "FunctionDeclaration" && parent.type !== "FunctionExpression";
|
|
2948
|
+
}
|
|
2949
|
+
|
|
2950
|
+
function isForWithConstLet(node) {
|
|
2951
|
+
return node.type === "ForStatement" && node.init && node.init.type === "VariableDeclaration" && isConstLet(node.init.kind);
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2954
|
+
function isForInOfWithConstLet(node) {
|
|
2955
|
+
return isForInOf(node) && node.left.type === "VariableDeclaration" && isConstLet(node.left.kind);
|
|
2956
|
+
}
|
|
2957
|
+
|
|
2958
|
+
function isForInOf(node) {
|
|
2959
|
+
return node.type === "ForInStatement" || node.type === "ForOfStatement";
|
|
2960
|
+
}
|
|
2961
|
+
|
|
2962
|
+
function isFunction(node) {
|
|
2963
|
+
return node.type === "FunctionDeclaration" || node.type === "FunctionExpression";
|
|
2964
|
+
}
|
|
2965
|
+
|
|
2966
|
+
function isReference(node) {
|
|
2967
|
+
var parent = node.$parent;
|
|
2968
|
+
return node.$refToScope ||
|
|
2969
|
+
node.type === "Identifier" &&
|
|
2970
|
+
!(parent.type === "VariableDeclarator" && parent.id === node) && // var|let|const $
|
|
2971
|
+
!(parent.type === "MemberExpression" && parent.computed === false && parent.property === node) && // obj.$
|
|
2972
|
+
!(parent.type === "Property" && parent.key === node) && // {$: ...}
|
|
2973
|
+
!(parent.type === "LabeledStatement" && parent.label === node) && // $: ...
|
|
2974
|
+
!(parent.type === "CatchClause" && parent.param === node) && // catch($)
|
|
2975
|
+
!(isFunction(parent) && parent.id === node) && // function $(..
|
|
2976
|
+
!(isFunction(parent) && is.someof(node, parent.params)) && // function f($)..
|
|
2977
|
+
true;
|
|
2978
|
+
}
|
|
2979
|
+
|
|
2980
|
+
},{"./scope":12,"assert":1,"ordered-ast-traverse":18,"simple-is":20}],14:[function(require,module,exports){
|
|
2981
|
+
// Acorn is a tiny, fast JavaScript parser written in JavaScript.
|
|
2982
|
+
//
|
|
2983
|
+
// Acorn was written by Marijn Haverbeke and various contributors and
|
|
2984
|
+
// released under an MIT license. The Unicode regexps (for identifiers
|
|
2985
|
+
// and whitespace) were taken from [Esprima](http://esprima.org) by
|
|
2986
|
+
// Ariya Hidayat.
|
|
2987
|
+
//
|
|
2988
|
+
// Git repositories for Acorn are available at
|
|
2989
|
+
//
|
|
2990
|
+
// http://marijnhaverbeke.nl/git/acorn
|
|
2991
|
+
// https://github.com/marijnh/acorn.git
|
|
2992
|
+
//
|
|
2993
|
+
// Please use the [github bug tracker][ghbt] to report issues.
|
|
2994
|
+
//
|
|
2995
|
+
// [ghbt]: https://github.com/marijnh/acorn/issues
|
|
2996
|
+
//
|
|
2997
|
+
// This file defines the main parser interface. The library also comes
|
|
2998
|
+
// with a [error-tolerant parser][dammit] and an
|
|
2999
|
+
// [abstract syntax tree walker][walk], defined in other files.
|
|
3000
|
+
//
|
|
3001
|
+
// [dammit]: acorn_loose.js
|
|
3002
|
+
// [walk]: util/walk.js
|
|
3003
|
+
|
|
3004
|
+
(function(root, mod) {
|
|
3005
|
+
if (typeof exports == "object" && typeof module == "object") return mod(exports); // CommonJS
|
|
3006
|
+
if (typeof define == "function" && define.amd) return define(["exports"], mod); // AMD
|
|
3007
|
+
mod(root.acorn || (root.acorn = {})); // Plain browser env
|
|
3008
|
+
})(this, function(exports) {
|
|
3009
|
+
"use strict";
|
|
3010
|
+
|
|
3011
|
+
exports.version = "0.9.0";
|
|
3012
|
+
|
|
3013
|
+
// The main exported interface (under `self.acorn` when in the
|
|
3014
|
+
// browser) is a `parse` function that takes a code string and
|
|
3015
|
+
// returns an abstract syntax tree as specified by [Mozilla parser
|
|
3016
|
+
// API][api], with the caveat that inline XML is not recognized.
|
|
3017
|
+
//
|
|
3018
|
+
// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
|
|
3019
|
+
|
|
3020
|
+
var options, input, inputLen, sourceFile;
|
|
3021
|
+
|
|
3022
|
+
exports.parse = function(inpt, opts) {
|
|
3023
|
+
input = String(inpt); inputLen = input.length;
|
|
3024
|
+
setOptions(opts);
|
|
3025
|
+
initTokenState();
|
|
3026
|
+
initParserState();
|
|
3027
|
+
return parseTopLevel(options.program);
|
|
3028
|
+
};
|
|
3029
|
+
|
|
3030
|
+
// A second optional argument can be given to further configure
|
|
3031
|
+
// the parser process. These options are recognized:
|
|
3032
|
+
|
|
3033
|
+
var defaultOptions = exports.defaultOptions = {
|
|
3034
|
+
// `ecmaVersion` indicates the ECMAScript version to parse. Must
|
|
3035
|
+
// be either 3, or 5, or 6. This influences support for strict
|
|
3036
|
+
// mode, the set of reserved words, support for getters and
|
|
3037
|
+
// setters and other features.
|
|
3038
|
+
ecmaVersion: 5,
|
|
3039
|
+
// Turn on `strictSemicolons` to prevent the parser from doing
|
|
3040
|
+
// automatic semicolon insertion.
|
|
3041
|
+
strictSemicolons: false,
|
|
3042
|
+
// When `allowTrailingCommas` is false, the parser will not allow
|
|
3043
|
+
// trailing commas in array and object literals.
|
|
3044
|
+
allowTrailingCommas: true,
|
|
3045
|
+
// By default, reserved words are not enforced. Enable
|
|
3046
|
+
// `forbidReserved` to enforce them. When this option has the
|
|
3047
|
+
// value "everywhere", reserved words and keywords can also not be
|
|
3048
|
+
// used as property names.
|
|
3049
|
+
forbidReserved: false,
|
|
3050
|
+
// When enabled, a return at the top level is not considered an
|
|
3051
|
+
// error.
|
|
3052
|
+
allowReturnOutsideFunction: false,
|
|
3053
|
+
// When `locations` is on, `loc` properties holding objects with
|
|
3054
|
+
// `start` and `end` properties in `{line, column}` form (with
|
|
3055
|
+
// line being 1-based and column 0-based) will be attached to the
|
|
3056
|
+
// nodes.
|
|
3057
|
+
locations: false,
|
|
3058
|
+
// A function can be passed as `onToken` option, which will
|
|
3059
|
+
// cause Acorn to call that function with object in the same
|
|
3060
|
+
// format as tokenize() returns. Note that you are not
|
|
3061
|
+
// allowed to call the parser from the callback—that will
|
|
3062
|
+
// corrupt its internal state.
|
|
3063
|
+
onToken: null,
|
|
3064
|
+
// A function can be passed as `onComment` option, which will
|
|
3065
|
+
// cause Acorn to call that function with `(block, text, start,
|
|
3066
|
+
// end)` parameters whenever a comment is skipped. `block` is a
|
|
3067
|
+
// boolean indicating whether this is a block (`/* */`) comment,
|
|
3068
|
+
// `text` is the content of the comment, and `start` and `end` are
|
|
3069
|
+
// character offsets that denote the start and end of the comment.
|
|
3070
|
+
// When the `locations` option is on, two more parameters are
|
|
3071
|
+
// passed, the full `{line, column}` locations of the start and
|
|
3072
|
+
// end of the comments. Note that you are not allowed to call the
|
|
3073
|
+
// parser from the callback—that will corrupt its internal state.
|
|
3074
|
+
onComment: null,
|
|
3075
|
+
// Nodes have their start and end characters offsets recorded in
|
|
3076
|
+
// `start` and `end` properties (directly on the node, rather than
|
|
3077
|
+
// the `loc` object, which holds line/column data. To also add a
|
|
3078
|
+
// [semi-standardized][range] `range` property holding a `[start,
|
|
3079
|
+
// end]` array with the same numbers, set the `ranges` option to
|
|
3080
|
+
// `true`.
|
|
3081
|
+
//
|
|
3082
|
+
// [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
|
|
3083
|
+
ranges: false,
|
|
3084
|
+
// It is possible to parse multiple files into a single AST by
|
|
3085
|
+
// passing the tree produced by parsing the first file as
|
|
3086
|
+
// `program` option in subsequent parses. This will add the
|
|
3087
|
+
// toplevel forms of the parsed file to the `Program` (top) node
|
|
3088
|
+
// of an existing parse tree.
|
|
3089
|
+
program: null,
|
|
3090
|
+
// When `locations` is on, you can pass this to record the source
|
|
3091
|
+
// file in every node's `loc` object.
|
|
3092
|
+
sourceFile: null,
|
|
3093
|
+
// This value, if given, is stored in every node, whether
|
|
3094
|
+
// `locations` is on or off.
|
|
3095
|
+
directSourceFile: null
|
|
3096
|
+
};
|
|
3097
|
+
|
|
3098
|
+
// This function tries to parse a single expression at a given
|
|
3099
|
+
// offset in a string. Useful for parsing mixed-language formats
|
|
3100
|
+
// that embed JavaScript expressions.
|
|
3101
|
+
|
|
3102
|
+
exports.parseExpressionAt = function(inpt, pos, opts) {
|
|
3103
|
+
input = String(inpt); inputLen = input.length;
|
|
3104
|
+
setOptions(opts);
|
|
3105
|
+
initTokenState(pos);
|
|
3106
|
+
initParserState();
|
|
3107
|
+
return parseExpression();
|
|
3108
|
+
};
|
|
3109
|
+
|
|
3110
|
+
var isArray = function (obj) {
|
|
3111
|
+
return Object.prototype.toString.call(obj) === "[object Array]";
|
|
3112
|
+
};
|
|
3113
|
+
|
|
3114
|
+
function setOptions(opts) {
|
|
3115
|
+
options = opts || {};
|
|
3116
|
+
for (var opt in defaultOptions) if (!has(options, opt))
|
|
3117
|
+
options[opt] = defaultOptions[opt];
|
|
3118
|
+
sourceFile = options.sourceFile || null;
|
|
3119
|
+
if (isArray(options.onToken)) {
|
|
3120
|
+
var tokens = options.onToken;
|
|
3121
|
+
options.onToken = function (token) {
|
|
3122
|
+
tokens.push(token);
|
|
3123
|
+
};
|
|
3124
|
+
}
|
|
3125
|
+
if (isArray(options.onComment)) {
|
|
3126
|
+
var comments = options.onComment;
|
|
3127
|
+
options.onComment = function (block, text, start, end, startLoc, endLoc) {
|
|
3128
|
+
var comment = {
|
|
3129
|
+
type: block ? 'Block' : 'Line',
|
|
3130
|
+
value: text,
|
|
3131
|
+
start: start,
|
|
3132
|
+
end: end
|
|
3133
|
+
};
|
|
3134
|
+
if (options.locations) {
|
|
3135
|
+
comment.loc = new SourceLocation();
|
|
3136
|
+
comment.loc.start = startLoc;
|
|
3137
|
+
comment.loc.end = endLoc;
|
|
3138
|
+
}
|
|
3139
|
+
if (options.ranges)
|
|
3140
|
+
comment.range = [start, end];
|
|
3141
|
+
comments.push(comment);
|
|
3142
|
+
};
|
|
3143
|
+
}
|
|
3144
|
+
isKeyword = options.ecmaVersion >= 6 ? isEcma6Keyword : isEcma5AndLessKeyword;
|
|
3145
|
+
}
|
|
3146
|
+
|
|
3147
|
+
// The `getLineInfo` function is mostly useful when the
|
|
3148
|
+
// `locations` option is off (for performance reasons) and you
|
|
3149
|
+
// want to find the line/column position for a given character
|
|
3150
|
+
// offset. `input` should be the code string that the offset refers
|
|
3151
|
+
// into.
|
|
3152
|
+
|
|
3153
|
+
var getLineInfo = exports.getLineInfo = function(input, offset) {
|
|
3154
|
+
for (var line = 1, cur = 0;;) {
|
|
3155
|
+
lineBreak.lastIndex = cur;
|
|
3156
|
+
var match = lineBreak.exec(input);
|
|
3157
|
+
if (match && match.index < offset) {
|
|
3158
|
+
++line;
|
|
3159
|
+
cur = match.index + match[0].length;
|
|
3160
|
+
} else break;
|
|
3161
|
+
}
|
|
3162
|
+
return {line: line, column: offset - cur};
|
|
3163
|
+
};
|
|
3164
|
+
|
|
3165
|
+
function Token() {
|
|
3166
|
+
this.type = tokType;
|
|
3167
|
+
this.value = tokVal;
|
|
3168
|
+
this.start = tokStart;
|
|
3169
|
+
this.end = tokEnd;
|
|
3170
|
+
if (options.locations) {
|
|
3171
|
+
this.loc = new SourceLocation();
|
|
3172
|
+
this.loc.end = tokEndLoc;
|
|
3173
|
+
// TODO: remove in next major release
|
|
3174
|
+
this.startLoc = tokStartLoc;
|
|
3175
|
+
this.endLoc = tokEndLoc;
|
|
3176
|
+
}
|
|
3177
|
+
if (options.ranges)
|
|
3178
|
+
this.range = [tokStart, tokEnd];
|
|
3179
|
+
}
|
|
3180
|
+
|
|
3181
|
+
exports.Token = Token;
|
|
3182
|
+
|
|
3183
|
+
// Acorn is organized as a tokenizer and a recursive-descent parser.
|
|
3184
|
+
// The `tokenize` export provides an interface to the tokenizer.
|
|
3185
|
+
// Because the tokenizer is optimized for being efficiently used by
|
|
3186
|
+
// the Acorn parser itself, this interface is somewhat crude and not
|
|
3187
|
+
// very modular. Performing another parse or call to `tokenize` will
|
|
3188
|
+
// reset the internal state, and invalidate existing tokenizers.
|
|
3189
|
+
|
|
3190
|
+
exports.tokenize = function(inpt, opts) {
|
|
3191
|
+
input = String(inpt); inputLen = input.length;
|
|
3192
|
+
setOptions(opts);
|
|
3193
|
+
initTokenState();
|
|
3194
|
+
|
|
3195
|
+
function getToken(forceRegexp) {
|
|
3196
|
+
lastEnd = tokEnd;
|
|
3197
|
+
readToken(forceRegexp);
|
|
3198
|
+
return new Token();
|
|
3199
|
+
}
|
|
3200
|
+
getToken.jumpTo = function(pos, reAllowed) {
|
|
3201
|
+
tokPos = pos;
|
|
3202
|
+
if (options.locations) {
|
|
3203
|
+
tokCurLine = 1;
|
|
3204
|
+
tokLineStart = lineBreak.lastIndex = 0;
|
|
3205
|
+
var match;
|
|
3206
|
+
while ((match = lineBreak.exec(input)) && match.index < pos) {
|
|
3207
|
+
++tokCurLine;
|
|
3208
|
+
tokLineStart = match.index + match[0].length;
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
tokRegexpAllowed = reAllowed;
|
|
3212
|
+
skipSpace();
|
|
3213
|
+
};
|
|
3214
|
+
return getToken;
|
|
3215
|
+
};
|
|
3216
|
+
|
|
3217
|
+
// State is kept in (closure-)global variables. We already saw the
|
|
3218
|
+
// `options`, `input`, and `inputLen` variables above.
|
|
3219
|
+
|
|
3220
|
+
// The current position of the tokenizer in the input.
|
|
3221
|
+
|
|
3222
|
+
var tokPos;
|
|
3223
|
+
|
|
3224
|
+
// The start and end offsets of the current token.
|
|
3225
|
+
|
|
3226
|
+
var tokStart, tokEnd;
|
|
3227
|
+
|
|
3228
|
+
// When `options.locations` is true, these hold objects
|
|
3229
|
+
// containing the tokens start and end line/column pairs.
|
|
3230
|
+
|
|
3231
|
+
var tokStartLoc, tokEndLoc;
|
|
3232
|
+
|
|
3233
|
+
// The type and value of the current token. Token types are objects,
|
|
3234
|
+
// named by variables against which they can be compared, and
|
|
3235
|
+
// holding properties that describe them (indicating, for example,
|
|
3236
|
+
// the precedence of an infix operator, and the original name of a
|
|
3237
|
+
// keyword token). The kind of value that's held in `tokVal` depends
|
|
3238
|
+
// on the type of the token. For literals, it is the literal value,
|
|
3239
|
+
// for operators, the operator name, and so on.
|
|
3240
|
+
|
|
3241
|
+
var tokType, tokVal;
|
|
3242
|
+
|
|
3243
|
+
// Internal state for the tokenizer. To distinguish between division
|
|
3244
|
+
// operators and regular expressions, it remembers whether the last
|
|
3245
|
+
// token was one that is allowed to be followed by an expression.
|
|
3246
|
+
// (If it is, a slash is probably a regexp, if it isn't it's a
|
|
3247
|
+
// division operator. See the `parseStatement` function for a
|
|
3248
|
+
// caveat.)
|
|
3249
|
+
|
|
3250
|
+
var tokRegexpAllowed;
|
|
3251
|
+
|
|
3252
|
+
// When `options.locations` is true, these are used to keep
|
|
3253
|
+
// track of the current line, and know when a new line has been
|
|
3254
|
+
// entered.
|
|
3255
|
+
|
|
3256
|
+
var tokCurLine, tokLineStart;
|
|
3257
|
+
|
|
3258
|
+
// These store the position of the previous token, which is useful
|
|
3259
|
+
// when finishing a node and assigning its `end` position.
|
|
3260
|
+
|
|
3261
|
+
var lastStart, lastEnd, lastEndLoc;
|
|
3262
|
+
|
|
3263
|
+
// This is the parser's state. `inFunction` is used to reject
|
|
3264
|
+
// `return` statements outside of functions, `inGenerator` to
|
|
3265
|
+
// reject `yield`s outside of generators, `labels` to verify
|
|
3266
|
+
// that `break` and `continue` have somewhere to jump to, and
|
|
3267
|
+
// `strict` indicates whether strict mode is on.
|
|
3268
|
+
|
|
3269
|
+
var inFunction, inGenerator, labels, strict;
|
|
3270
|
+
|
|
3271
|
+
// This counter is used for checking that arrow expressions did
|
|
3272
|
+
// not contain nested parentheses in argument list.
|
|
3273
|
+
|
|
3274
|
+
var metParenL;
|
|
3275
|
+
|
|
3276
|
+
// This is used by parser for detecting if it's inside ES6
|
|
3277
|
+
// Template String. If it is, it should treat '$' as prefix before
|
|
3278
|
+
// '{expression}' and everything else as string literals.
|
|
3279
|
+
|
|
3280
|
+
var inTemplate;
|
|
3281
|
+
|
|
3282
|
+
function initParserState() {
|
|
3283
|
+
lastStart = lastEnd = tokPos;
|
|
3284
|
+
if (options.locations) lastEndLoc = new Position;
|
|
3285
|
+
inFunction = inGenerator = strict = false;
|
|
3286
|
+
labels = [];
|
|
3287
|
+
readToken();
|
|
3288
|
+
}
|
|
3289
|
+
|
|
3290
|
+
// This function is used to raise exceptions on parse errors. It
|
|
3291
|
+
// takes an offset integer (into the current `input`) to indicate
|
|
3292
|
+
// the location of the error, attaches the position to the end
|
|
3293
|
+
// of the error message, and then raises a `SyntaxError` with that
|
|
3294
|
+
// message.
|
|
3295
|
+
|
|
3296
|
+
function raise(pos, message) {
|
|
3297
|
+
var loc = getLineInfo(input, pos);
|
|
3298
|
+
message += " (" + loc.line + ":" + loc.column + ")";
|
|
3299
|
+
var err = new SyntaxError(message);
|
|
3300
|
+
err.pos = pos; err.loc = loc; err.raisedAt = tokPos;
|
|
3301
|
+
throw err;
|
|
3302
|
+
}
|
|
3303
|
+
|
|
3304
|
+
// Reused empty array added for node fields that are always empty.
|
|
3305
|
+
|
|
3306
|
+
var empty = [];
|
|
3307
|
+
|
|
3308
|
+
// ## Token types
|
|
3309
|
+
|
|
3310
|
+
// The assignment of fine-grained, information-carrying type objects
|
|
3311
|
+
// allows the tokenizer to store the information it has about a
|
|
3312
|
+
// token in a way that is very cheap for the parser to look up.
|
|
3313
|
+
|
|
3314
|
+
// All token type variables start with an underscore, to make them
|
|
3315
|
+
// easy to recognize.
|
|
3316
|
+
|
|
3317
|
+
// These are the general types. The `type` property is only used to
|
|
3318
|
+
// make them recognizeable when debugging.
|
|
3319
|
+
|
|
3320
|
+
var _num = {type: "num"}, _regexp = {type: "regexp"}, _string = {type: "string"};
|
|
3321
|
+
var _name = {type: "name"}, _eof = {type: "eof"};
|
|
3322
|
+
|
|
3323
|
+
// Keyword tokens. The `keyword` property (also used in keyword-like
|
|
3324
|
+
// operators) indicates that the token originated from an
|
|
3325
|
+
// identifier-like word, which is used when parsing property names.
|
|
3326
|
+
//
|
|
3327
|
+
// The `beforeExpr` property is used to disambiguate between regular
|
|
3328
|
+
// expressions and divisions. It is set on all token types that can
|
|
3329
|
+
// be followed by an expression (thus, a slash after them would be a
|
|
3330
|
+
// regular expression).
|
|
3331
|
+
//
|
|
3332
|
+
// `isLoop` marks a keyword as starting a loop, which is important
|
|
3333
|
+
// to know when parsing a label, in order to allow or disallow
|
|
3334
|
+
// continue jumps to that label.
|
|
3335
|
+
|
|
3336
|
+
var _break = {keyword: "break"}, _case = {keyword: "case", beforeExpr: true}, _catch = {keyword: "catch"};
|
|
3337
|
+
var _continue = {keyword: "continue"}, _debugger = {keyword: "debugger"}, _default = {keyword: "default"};
|
|
3338
|
+
var _do = {keyword: "do", isLoop: true}, _else = {keyword: "else", beforeExpr: true};
|
|
3339
|
+
var _finally = {keyword: "finally"}, _for = {keyword: "for", isLoop: true}, _function = {keyword: "function"};
|
|
3340
|
+
var _if = {keyword: "if"}, _return = {keyword: "return", beforeExpr: true}, _switch = {keyword: "switch"};
|
|
3341
|
+
var _throw = {keyword: "throw", beforeExpr: true}, _try = {keyword: "try"}, _var = {keyword: "var"};
|
|
3342
|
+
var _let = {keyword: "let"}, _const = {keyword: "const"};
|
|
3343
|
+
var _while = {keyword: "while", isLoop: true}, _with = {keyword: "with"}, _new = {keyword: "new", beforeExpr: true};
|
|
3344
|
+
var _this = {keyword: "this"};
|
|
3345
|
+
var _class = {keyword: "class"}, _extends = {keyword: "extends", beforeExpr: true};
|
|
3346
|
+
var _export = {keyword: "export"}, _import = {keyword: "import"};
|
|
3347
|
+
var _yield = {keyword: "yield", beforeExpr: true};
|
|
3348
|
+
|
|
3349
|
+
// The keywords that denote values.
|
|
3350
|
+
|
|
3351
|
+
var _null = {keyword: "null", atomValue: null}, _true = {keyword: "true", atomValue: true};
|
|
3352
|
+
var _false = {keyword: "false", atomValue: false};
|
|
3353
|
+
|
|
3354
|
+
// Some keywords are treated as regular operators. `in` sometimes
|
|
3355
|
+
// (when parsing `for`) needs to be tested against specifically, so
|
|
3356
|
+
// we assign a variable name to it for quick comparing.
|
|
3357
|
+
|
|
3358
|
+
var _in = {keyword: "in", binop: 7, beforeExpr: true};
|
|
3359
|
+
|
|
3360
|
+
// Map keyword names to token types.
|
|
3361
|
+
|
|
3362
|
+
var keywordTypes = {"break": _break, "case": _case, "catch": _catch,
|
|
3363
|
+
"continue": _continue, "debugger": _debugger, "default": _default,
|
|
3364
|
+
"do": _do, "else": _else, "finally": _finally, "for": _for,
|
|
3365
|
+
"function": _function, "if": _if, "return": _return, "switch": _switch,
|
|
3366
|
+
"throw": _throw, "try": _try, "var": _var, "let": _let, "const": _const,
|
|
3367
|
+
"while": _while, "with": _with,
|
|
3368
|
+
"null": _null, "true": _true, "false": _false, "new": _new, "in": _in,
|
|
3369
|
+
"instanceof": {keyword: "instanceof", binop: 7, beforeExpr: true}, "this": _this,
|
|
3370
|
+
"typeof": {keyword: "typeof", prefix: true, beforeExpr: true},
|
|
3371
|
+
"void": {keyword: "void", prefix: true, beforeExpr: true},
|
|
3372
|
+
"delete": {keyword: "delete", prefix: true, beforeExpr: true},
|
|
3373
|
+
"class": _class, "extends": _extends,
|
|
3374
|
+
"export": _export, "import": _import, "yield": _yield};
|
|
3375
|
+
|
|
3376
|
+
// Punctuation token types. Again, the `type` property is purely for debugging.
|
|
3377
|
+
|
|
3378
|
+
var _bracketL = {type: "[", beforeExpr: true}, _bracketR = {type: "]"}, _braceL = {type: "{", beforeExpr: true};
|
|
3379
|
+
var _braceR = {type: "}"}, _parenL = {type: "(", beforeExpr: true}, _parenR = {type: ")"};
|
|
3380
|
+
var _comma = {type: ",", beforeExpr: true}, _semi = {type: ";", beforeExpr: true};
|
|
3381
|
+
var _colon = {type: ":", beforeExpr: true}, _dot = {type: "."}, _ellipsis = {type: "..."}, _question = {type: "?", beforeExpr: true};
|
|
3382
|
+
var _arrow = {type: "=>", beforeExpr: true}, _bquote = {type: "`"}, _dollarBraceL = {type: "${", beforeExpr: true};
|
|
3383
|
+
|
|
3384
|
+
// Operators. These carry several kinds of properties to help the
|
|
3385
|
+
// parser use them properly (the presence of these properties is
|
|
3386
|
+
// what categorizes them as operators).
|
|
3387
|
+
//
|
|
3388
|
+
// `binop`, when present, specifies that this operator is a binary
|
|
3389
|
+
// operator, and will refer to its precedence.
|
|
3390
|
+
//
|
|
3391
|
+
// `prefix` and `postfix` mark the operator as a prefix or postfix
|
|
3392
|
+
// unary operator. `isUpdate` specifies that the node produced by
|
|
3393
|
+
// the operator should be of type UpdateExpression rather than
|
|
3394
|
+
// simply UnaryExpression (`++` and `--`).
|
|
3395
|
+
//
|
|
3396
|
+
// `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
|
|
3397
|
+
// binary operators with a very low precedence, that should result
|
|
3398
|
+
// in AssignmentExpression nodes.
|
|
3399
|
+
|
|
3400
|
+
var _slash = {binop: 10, beforeExpr: true}, _eq = {isAssign: true, beforeExpr: true};
|
|
3401
|
+
var _assign = {isAssign: true, beforeExpr: true};
|
|
3402
|
+
var _incDec = {postfix: true, prefix: true, isUpdate: true}, _prefix = {prefix: true, beforeExpr: true};
|
|
3403
|
+
var _logicalOR = {binop: 1, beforeExpr: true};
|
|
3404
|
+
var _logicalAND = {binop: 2, beforeExpr: true};
|
|
3405
|
+
var _bitwiseOR = {binop: 3, beforeExpr: true};
|
|
3406
|
+
var _bitwiseXOR = {binop: 4, beforeExpr: true};
|
|
3407
|
+
var _bitwiseAND = {binop: 5, beforeExpr: true};
|
|
3408
|
+
var _equality = {binop: 6, beforeExpr: true};
|
|
3409
|
+
var _relational = {binop: 7, beforeExpr: true};
|
|
3410
|
+
var _bitShift = {binop: 8, beforeExpr: true};
|
|
3411
|
+
var _plusMin = {binop: 9, prefix: true, beforeExpr: true};
|
|
3412
|
+
var _modulo = {binop: 10, beforeExpr: true};
|
|
3413
|
+
|
|
3414
|
+
// '*' may be multiply or have special meaning in ES6
|
|
3415
|
+
var _star = {binop: 10, beforeExpr: true};
|
|
3416
|
+
|
|
3417
|
+
// Provide access to the token types for external users of the
|
|
3418
|
+
// tokenizer.
|
|
3419
|
+
|
|
3420
|
+
exports.tokTypes = {bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR,
|
|
3421
|
+
parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon,
|
|
3422
|
+
dot: _dot, ellipsis: _ellipsis, question: _question, slash: _slash, eq: _eq,
|
|
3423
|
+
name: _name, eof: _eof, num: _num, regexp: _regexp, string: _string,
|
|
3424
|
+
arrow: _arrow, bquote: _bquote, dollarBraceL: _dollarBraceL};
|
|
3425
|
+
for (var kw in keywordTypes) exports.tokTypes["_" + kw] = keywordTypes[kw];
|
|
3426
|
+
|
|
3427
|
+
// This is a trick taken from Esprima. It turns out that, on
|
|
3428
|
+
// non-Chrome browsers, to check whether a string is in a set, a
|
|
3429
|
+
// predicate containing a big ugly `switch` statement is faster than
|
|
3430
|
+
// a regular expression, and on Chrome the two are about on par.
|
|
3431
|
+
// This function uses `eval` (non-lexical) to produce such a
|
|
3432
|
+
// predicate from a space-separated string of words.
|
|
3433
|
+
//
|
|
3434
|
+
// It starts by sorting the words by length.
|
|
3435
|
+
|
|
3436
|
+
function makePredicate(words) {
|
|
3437
|
+
words = words.split(" ");
|
|
3438
|
+
var f = "", cats = [];
|
|
3439
|
+
out: for (var i = 0; i < words.length; ++i) {
|
|
3440
|
+
for (var j = 0; j < cats.length; ++j)
|
|
3441
|
+
if (cats[j][0].length == words[i].length) {
|
|
3442
|
+
cats[j].push(words[i]);
|
|
3443
|
+
continue out;
|
|
3444
|
+
}
|
|
3445
|
+
cats.push([words[i]]);
|
|
3446
|
+
}
|
|
3447
|
+
function compareTo(arr) {
|
|
3448
|
+
if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";";
|
|
3449
|
+
f += "switch(str){";
|
|
3450
|
+
for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":";
|
|
3451
|
+
f += "return true}return false;";
|
|
3452
|
+
}
|
|
3453
|
+
|
|
3454
|
+
// When there are more than three length categories, an outer
|
|
3455
|
+
// switch first dispatches on the lengths, to save on comparisons.
|
|
3456
|
+
|
|
3457
|
+
if (cats.length > 3) {
|
|
3458
|
+
cats.sort(function(a, b) {return b.length - a.length;});
|
|
3459
|
+
f += "switch(str.length){";
|
|
3460
|
+
for (var i = 0; i < cats.length; ++i) {
|
|
3461
|
+
var cat = cats[i];
|
|
3462
|
+
f += "case " + cat[0].length + ":";
|
|
3463
|
+
compareTo(cat);
|
|
3464
|
+
}
|
|
3465
|
+
f += "}";
|
|
3466
|
+
|
|
3467
|
+
// Otherwise, simply generate a flat `switch` statement.
|
|
3468
|
+
|
|
3469
|
+
} else {
|
|
3470
|
+
compareTo(words);
|
|
3471
|
+
}
|
|
3472
|
+
return new Function("str", f);
|
|
3473
|
+
}
|
|
3474
|
+
|
|
3475
|
+
// The ECMAScript 3 reserved word list.
|
|
3476
|
+
|
|
3477
|
+
var isReservedWord3 = makePredicate("abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile");
|
|
3478
|
+
|
|
3479
|
+
// ECMAScript 5 reserved words.
|
|
3480
|
+
|
|
3481
|
+
var isReservedWord5 = makePredicate("class enum extends super const export import");
|
|
3482
|
+
|
|
3483
|
+
// The additional reserved words in strict mode.
|
|
3484
|
+
|
|
3485
|
+
var isStrictReservedWord = makePredicate("implements interface let package private protected public static yield");
|
|
3486
|
+
|
|
3487
|
+
// The forbidden variable names in strict mode.
|
|
3488
|
+
|
|
3489
|
+
var isStrictBadIdWord = makePredicate("eval arguments");
|
|
3490
|
+
|
|
3491
|
+
// And the keywords.
|
|
3492
|
+
|
|
3493
|
+
var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";
|
|
3494
|
+
|
|
3495
|
+
var isEcma5AndLessKeyword = makePredicate(ecma5AndLessKeywords);
|
|
3496
|
+
|
|
3497
|
+
var isEcma6Keyword = makePredicate(ecma5AndLessKeywords + " let const class extends export import yield");
|
|
3498
|
+
|
|
3499
|
+
var isKeyword = isEcma5AndLessKeyword;
|
|
3500
|
+
|
|
3501
|
+
// ## Character categories
|
|
3502
|
+
|
|
3503
|
+
// Big ugly regular expressions that match characters in the
|
|
3504
|
+
// whitespace, identifier, and identifier-start categories. These
|
|
3505
|
+
// are only applied when a character is found to actually have a
|
|
3506
|
+
// code point above 128.
|
|
3507
|
+
// Generated by `tools/generate-identifier-regex.js`.
|
|
3508
|
+
|
|
3509
|
+
var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
|
|
3510
|
+
var nonASCIIidentifierStartChars = "\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC";
|
|
3511
|
+
var nonASCIIidentifierChars = "\u0300-\u036F\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u0669\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u06F0-\u06F9\u0711\u0730-\u074A\u07A6-\u07B0\u07C0-\u07C9\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E4-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0966-\u096F\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09E6-\u09EF\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A66-\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B66-\u0B6F\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0CE6-\u0CEF\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D66-\u0D6F\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0E50-\u0E59\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0ED0-\u0ED9\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1040-\u1049\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u18A9\u1920-\u192B\u1930-\u193B\u1946-\u194F\u19B0-\u19C0\u19C8\u19C9\u19D0-\u19D9\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AB0-\u1ABD\u1B00-\u1B04\u1B34-\u1B44\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BF3\u1C24-\u1C37\u1C40-\u1C49\u1C50-\u1C59\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFC-\u1DFF\u200C\u200D\u203F\u2040\u2054\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA620-\uA629\uA66F\uA674-\uA67D\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F1\uA900-\uA909\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9D0-\uA9D9\uA9E5\uA9F0-\uA9F9\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA50-\uAA59\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uABF0-\uABF9\uFB1E\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFF10-\uFF19\uFF3F";
|
|
3512
|
+
var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
|
|
3513
|
+
var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
|
|
3514
|
+
|
|
3515
|
+
// Whether a single character denotes a newline.
|
|
3516
|
+
|
|
3517
|
+
var newline = /[\n\r\u2028\u2029]/;
|
|
3518
|
+
|
|
3519
|
+
// Matches a whole line break (where CRLF is considered a single
|
|
3520
|
+
// line break). Used to count lines.
|
|
3521
|
+
|
|
3522
|
+
var lineBreak = /\r\n|[\n\r\u2028\u2029]/g;
|
|
3523
|
+
|
|
3524
|
+
// Test whether a given character code starts an identifier.
|
|
3525
|
+
|
|
3526
|
+
var isIdentifierStart = exports.isIdentifierStart = function(code) {
|
|
3527
|
+
if (code < 65) return code === 36;
|
|
3528
|
+
if (code < 91) return true;
|
|
3529
|
+
if (code < 97) return code === 95;
|
|
3530
|
+
if (code < 123)return true;
|
|
3531
|
+
return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));
|
|
3532
|
+
};
|
|
3533
|
+
|
|
3534
|
+
// Test whether a given character is part of an identifier.
|
|
3535
|
+
|
|
3536
|
+
var isIdentifierChar = exports.isIdentifierChar = function(code) {
|
|
3537
|
+
if (code < 48) return code === 36;
|
|
3538
|
+
if (code < 58) return true;
|
|
3539
|
+
if (code < 65) return false;
|
|
3540
|
+
if (code < 91) return true;
|
|
3541
|
+
if (code < 97) return code === 95;
|
|
3542
|
+
if (code < 123)return true;
|
|
3543
|
+
return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));
|
|
3544
|
+
};
|
|
3545
|
+
|
|
3546
|
+
// ## Tokenizer
|
|
3547
|
+
|
|
3548
|
+
// These are used when `options.locations` is on, for the
|
|
3549
|
+
// `tokStartLoc` and `tokEndLoc` properties.
|
|
3550
|
+
|
|
3551
|
+
function Position() {
|
|
3552
|
+
this.line = tokCurLine;
|
|
3553
|
+
this.column = tokPos - tokLineStart;
|
|
3554
|
+
}
|
|
3555
|
+
|
|
3556
|
+
// Reset the token state. Used at the start of a parse.
|
|
3557
|
+
|
|
3558
|
+
function initTokenState(pos) {
|
|
3559
|
+
if (pos) {
|
|
3560
|
+
tokPos = pos;
|
|
3561
|
+
tokLineStart = Math.max(0, input.lastIndexOf("\n", pos));
|
|
3562
|
+
tokCurLine = input.slice(0, tokLineStart).split(newline).length;
|
|
3563
|
+
} else {
|
|
3564
|
+
tokCurLine = 1;
|
|
3565
|
+
tokPos = tokLineStart = 0;
|
|
3566
|
+
}
|
|
3567
|
+
tokRegexpAllowed = true;
|
|
3568
|
+
metParenL = 0;
|
|
3569
|
+
inTemplate = false;
|
|
3570
|
+
skipSpace();
|
|
3571
|
+
}
|
|
3572
|
+
|
|
3573
|
+
// Called at the end of every token. Sets `tokEnd`, `tokVal`, and
|
|
3574
|
+
// `tokRegexpAllowed`, and skips the space after the token, so that
|
|
3575
|
+
// the next one's `tokStart` will point at the right position.
|
|
3576
|
+
|
|
3577
|
+
function finishToken(type, val, shouldSkipSpace) {
|
|
3578
|
+
tokEnd = tokPos;
|
|
3579
|
+
if (options.locations) tokEndLoc = new Position;
|
|
3580
|
+
tokType = type;
|
|
3581
|
+
if (shouldSkipSpace !== false) skipSpace();
|
|
3582
|
+
tokVal = val;
|
|
3583
|
+
tokRegexpAllowed = type.beforeExpr;
|
|
3584
|
+
if (options.onToken) {
|
|
3585
|
+
options.onToken(new Token());
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
|
|
3589
|
+
function skipBlockComment() {
|
|
3590
|
+
var startLoc = options.onComment && options.locations && new Position;
|
|
3591
|
+
var start = tokPos, end = input.indexOf("*/", tokPos += 2);
|
|
3592
|
+
if (end === -1) raise(tokPos - 2, "Unterminated comment");
|
|
3593
|
+
tokPos = end + 2;
|
|
3594
|
+
if (options.locations) {
|
|
3595
|
+
lineBreak.lastIndex = start;
|
|
3596
|
+
var match;
|
|
3597
|
+
while ((match = lineBreak.exec(input)) && match.index < tokPos) {
|
|
3598
|
+
++tokCurLine;
|
|
3599
|
+
tokLineStart = match.index + match[0].length;
|
|
3600
|
+
}
|
|
3601
|
+
}
|
|
3602
|
+
if (options.onComment)
|
|
3603
|
+
options.onComment(true, input.slice(start + 2, end), start, tokPos,
|
|
3604
|
+
startLoc, options.locations && new Position);
|
|
3605
|
+
}
|
|
3606
|
+
|
|
3607
|
+
function skipLineComment(startSkip) {
|
|
3608
|
+
var start = tokPos;
|
|
3609
|
+
var startLoc = options.onComment && options.locations && new Position;
|
|
3610
|
+
var ch = input.charCodeAt(tokPos+=startSkip);
|
|
3611
|
+
while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) {
|
|
3612
|
+
++tokPos;
|
|
3613
|
+
ch = input.charCodeAt(tokPos);
|
|
3614
|
+
}
|
|
3615
|
+
if (options.onComment)
|
|
3616
|
+
options.onComment(false, input.slice(start + startSkip, tokPos), start, tokPos,
|
|
3617
|
+
startLoc, options.locations && new Position);
|
|
3618
|
+
}
|
|
3619
|
+
|
|
3620
|
+
// Called at the start of the parse and after every token. Skips
|
|
3621
|
+
// whitespace and comments, and.
|
|
3622
|
+
|
|
3623
|
+
function skipSpace() {
|
|
3624
|
+
while (tokPos < inputLen) {
|
|
3625
|
+
var ch = input.charCodeAt(tokPos);
|
|
3626
|
+
if (ch === 32) { // ' '
|
|
3627
|
+
++tokPos;
|
|
3628
|
+
} else if (ch === 13) {
|
|
3629
|
+
++tokPos;
|
|
3630
|
+
var next = input.charCodeAt(tokPos);
|
|
3631
|
+
if (next === 10) {
|
|
3632
|
+
++tokPos;
|
|
3633
|
+
}
|
|
3634
|
+
if (options.locations) {
|
|
3635
|
+
++tokCurLine;
|
|
3636
|
+
tokLineStart = tokPos;
|
|
3637
|
+
}
|
|
3638
|
+
} else if (ch === 10 || ch === 8232 || ch === 8233) {
|
|
3639
|
+
++tokPos;
|
|
3640
|
+
if (options.locations) {
|
|
3641
|
+
++tokCurLine;
|
|
3642
|
+
tokLineStart = tokPos;
|
|
3643
|
+
}
|
|
3644
|
+
} else if (ch > 8 && ch < 14) {
|
|
3645
|
+
++tokPos;
|
|
3646
|
+
} else if (ch === 47) { // '/'
|
|
3647
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
3648
|
+
if (next === 42) { // '*'
|
|
3649
|
+
skipBlockComment();
|
|
3650
|
+
} else if (next === 47) { // '/'
|
|
3651
|
+
skipLineComment(2);
|
|
3652
|
+
} else break;
|
|
3653
|
+
} else if (ch === 160) { // '\xa0'
|
|
3654
|
+
++tokPos;
|
|
3655
|
+
} else if (ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
|
|
3656
|
+
++tokPos;
|
|
3657
|
+
} else {
|
|
3658
|
+
break;
|
|
3659
|
+
}
|
|
3660
|
+
}
|
|
3661
|
+
}
|
|
3662
|
+
|
|
3663
|
+
// ### Token reading
|
|
3664
|
+
|
|
3665
|
+
// This is the function that is called to fetch the next token. It
|
|
3666
|
+
// is somewhat obscure, because it works in character codes rather
|
|
3667
|
+
// than characters, and because operator parsing has been inlined
|
|
3668
|
+
// into it.
|
|
3669
|
+
//
|
|
3670
|
+
// All in the name of speed.
|
|
3671
|
+
//
|
|
3672
|
+
// The `forceRegexp` parameter is used in the one case where the
|
|
3673
|
+
// `tokRegexpAllowed` trick does not work. See `parseStatement`.
|
|
3674
|
+
|
|
3675
|
+
function readToken_dot() {
|
|
3676
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
3677
|
+
if (next >= 48 && next <= 57) return readNumber(true);
|
|
3678
|
+
var next2 = input.charCodeAt(tokPos + 2);
|
|
3679
|
+
if (options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
|
|
3680
|
+
tokPos += 3;
|
|
3681
|
+
return finishToken(_ellipsis);
|
|
3682
|
+
} else {
|
|
3683
|
+
++tokPos;
|
|
3684
|
+
return finishToken(_dot);
|
|
3685
|
+
}
|
|
3686
|
+
}
|
|
3687
|
+
|
|
3688
|
+
function readToken_slash() { // '/'
|
|
3689
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
3690
|
+
if (tokRegexpAllowed) {++tokPos; return readRegexp();}
|
|
3691
|
+
if (next === 61) return finishOp(_assign, 2);
|
|
3692
|
+
return finishOp(_slash, 1);
|
|
3693
|
+
}
|
|
3694
|
+
|
|
3695
|
+
function readToken_mult_modulo(code) { // '%*'
|
|
3696
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
3697
|
+
if (next === 61) return finishOp(_assign, 2);
|
|
3698
|
+
return finishOp(code === 42 ? _star : _modulo, 1);
|
|
3699
|
+
}
|
|
3700
|
+
|
|
3701
|
+
function readToken_pipe_amp(code) { // '|&'
|
|
3702
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
3703
|
+
if (next === code) return finishOp(code === 124 ? _logicalOR : _logicalAND, 2);
|
|
3704
|
+
if (next === 61) return finishOp(_assign, 2);
|
|
3705
|
+
return finishOp(code === 124 ? _bitwiseOR : _bitwiseAND, 1);
|
|
3706
|
+
}
|
|
3707
|
+
|
|
3708
|
+
function readToken_caret() { // '^'
|
|
3709
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
3710
|
+
if (next === 61) return finishOp(_assign, 2);
|
|
3711
|
+
return finishOp(_bitwiseXOR, 1);
|
|
3712
|
+
}
|
|
3713
|
+
|
|
3714
|
+
function readToken_plus_min(code) { // '+-'
|
|
3715
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
3716
|
+
if (next === code) {
|
|
3717
|
+
if (next == 45 && input.charCodeAt(tokPos + 2) == 62 &&
|
|
3718
|
+
newline.test(input.slice(lastEnd, tokPos))) {
|
|
3719
|
+
// A `-->` line comment
|
|
3720
|
+
skipLineComment(3);
|
|
3721
|
+
skipSpace();
|
|
3722
|
+
return readToken();
|
|
3723
|
+
}
|
|
3724
|
+
return finishOp(_incDec, 2);
|
|
3725
|
+
}
|
|
3726
|
+
if (next === 61) return finishOp(_assign, 2);
|
|
3727
|
+
return finishOp(_plusMin, 1);
|
|
3728
|
+
}
|
|
3729
|
+
|
|
3730
|
+
function readToken_lt_gt(code) { // '<>'
|
|
3731
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
3732
|
+
var size = 1;
|
|
3733
|
+
if (next === code) {
|
|
3734
|
+
size = code === 62 && input.charCodeAt(tokPos + 2) === 62 ? 3 : 2;
|
|
3735
|
+
if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1);
|
|
3736
|
+
return finishOp(_bitShift, size);
|
|
3737
|
+
}
|
|
3738
|
+
if (next == 33 && code == 60 && input.charCodeAt(tokPos + 2) == 45 &&
|
|
3739
|
+
input.charCodeAt(tokPos + 3) == 45) {
|
|
3740
|
+
// `<!--`, an XML-style comment that should be interpreted as a line comment
|
|
3741
|
+
skipLineComment(4);
|
|
3742
|
+
skipSpace();
|
|
3743
|
+
return readToken();
|
|
3744
|
+
}
|
|
3745
|
+
if (next === 61)
|
|
3746
|
+
size = input.charCodeAt(tokPos + 2) === 61 ? 3 : 2;
|
|
3747
|
+
return finishOp(_relational, size);
|
|
3748
|
+
}
|
|
3749
|
+
|
|
3750
|
+
function readToken_eq_excl(code) { // '=!', '=>'
|
|
3751
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
3752
|
+
if (next === 61) return finishOp(_equality, input.charCodeAt(tokPos + 2) === 61 ? 3 : 2);
|
|
3753
|
+
if (code === 61 && next === 62 && options.ecmaVersion >= 6) { // '=>'
|
|
3754
|
+
tokPos += 2;
|
|
3755
|
+
return finishToken(_arrow);
|
|
3756
|
+
}
|
|
3757
|
+
return finishOp(code === 61 ? _eq : _prefix, 1);
|
|
3758
|
+
}
|
|
3759
|
+
|
|
3760
|
+
// Get token inside ES6 template (special rules work there).
|
|
3761
|
+
|
|
3762
|
+
function getTemplateToken(code) {
|
|
3763
|
+
// '`' and '${' have special meanings, but they should follow
|
|
3764
|
+
// string (can be empty)
|
|
3765
|
+
if (tokType === _string) {
|
|
3766
|
+
if (code === 96) { // '`'
|
|
3767
|
+
++tokPos;
|
|
3768
|
+
return finishToken(_bquote);
|
|
3769
|
+
} else
|
|
3770
|
+
if (code === 36 && input.charCodeAt(tokPos + 1) === 123) { // '${'
|
|
3771
|
+
tokPos += 2;
|
|
3772
|
+
return finishToken(_dollarBraceL);
|
|
3773
|
+
}
|
|
3774
|
+
}
|
|
3775
|
+
|
|
3776
|
+
if (code === 125) { // '}'
|
|
3777
|
+
++tokPos;
|
|
3778
|
+
return finishToken(_braceR, undefined, false);
|
|
3779
|
+
}
|
|
3780
|
+
|
|
3781
|
+
// anything else is considered string literal
|
|
3782
|
+
return readTmplString();
|
|
3783
|
+
}
|
|
3784
|
+
|
|
3785
|
+
function getTokenFromCode(code) {
|
|
3786
|
+
switch (code) {
|
|
3787
|
+
// The interpretation of a dot depends on whether it is followed
|
|
3788
|
+
// by a digit or another two dots.
|
|
3789
|
+
case 46: // '.'
|
|
3790
|
+
return readToken_dot();
|
|
3791
|
+
|
|
3792
|
+
// Punctuation tokens.
|
|
3793
|
+
case 40: ++tokPos; return finishToken(_parenL);
|
|
3794
|
+
case 41: ++tokPos; return finishToken(_parenR);
|
|
3795
|
+
case 59: ++tokPos; return finishToken(_semi);
|
|
3796
|
+
case 44: ++tokPos; return finishToken(_comma);
|
|
3797
|
+
case 91: ++tokPos; return finishToken(_bracketL);
|
|
3798
|
+
case 93: ++tokPos; return finishToken(_bracketR);
|
|
3799
|
+
case 123: ++tokPos; return finishToken(_braceL);
|
|
3800
|
+
case 125: ++tokPos; return finishToken(_braceR);
|
|
3801
|
+
case 58: ++tokPos; return finishToken(_colon);
|
|
3802
|
+
case 63: ++tokPos; return finishToken(_question);
|
|
3803
|
+
|
|
3804
|
+
case 96: // '`'
|
|
3805
|
+
if (options.ecmaVersion >= 6) {
|
|
3806
|
+
++tokPos;
|
|
3807
|
+
return finishToken(_bquote, undefined, false);
|
|
3808
|
+
}
|
|
3809
|
+
|
|
3810
|
+
case 48: // '0'
|
|
3811
|
+
var next = input.charCodeAt(tokPos + 1);
|
|
3812
|
+
if (next === 120 || next === 88) return readRadixNumber(16); // '0x', '0X' - hex number
|
|
3813
|
+
if (options.ecmaVersion >= 6) {
|
|
3814
|
+
if (next === 111 || next === 79) return readRadixNumber(8); // '0o', '0O' - octal number
|
|
3815
|
+
if (next === 98 || next === 66) return readRadixNumber(2); // '0b', '0B' - binary number
|
|
3816
|
+
}
|
|
3817
|
+
// Anything else beginning with a digit is an integer, octal
|
|
3818
|
+
// number, or float.
|
|
3819
|
+
case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
|
|
3820
|
+
return readNumber(false);
|
|
3821
|
+
|
|
3822
|
+
// Quotes produce strings.
|
|
3823
|
+
case 34: case 39: // '"', "'"
|
|
3824
|
+
return readString(code);
|
|
3825
|
+
|
|
3826
|
+
// Operators are parsed inline in tiny state machines. '=' (61) is
|
|
3827
|
+
// often referred to. `finishOp` simply skips the amount of
|
|
3828
|
+
// characters it is given as second argument, and returns a token
|
|
3829
|
+
// of the type given by its first argument.
|
|
3830
|
+
|
|
3831
|
+
case 47: // '/'
|
|
3832
|
+
return readToken_slash();
|
|
3833
|
+
|
|
3834
|
+
case 37: case 42: // '%*'
|
|
3835
|
+
return readToken_mult_modulo(code);
|
|
3836
|
+
|
|
3837
|
+
case 124: case 38: // '|&'
|
|
3838
|
+
return readToken_pipe_amp(code);
|
|
3839
|
+
|
|
3840
|
+
case 94: // '^'
|
|
3841
|
+
return readToken_caret();
|
|
3842
|
+
|
|
3843
|
+
case 43: case 45: // '+-'
|
|
3844
|
+
return readToken_plus_min(code);
|
|
3845
|
+
|
|
3846
|
+
case 60: case 62: // '<>'
|
|
3847
|
+
return readToken_lt_gt(code);
|
|
3848
|
+
|
|
3849
|
+
case 61: case 33: // '=!'
|
|
3850
|
+
return readToken_eq_excl(code);
|
|
3851
|
+
|
|
3852
|
+
case 126: // '~'
|
|
3853
|
+
return finishOp(_prefix, 1);
|
|
3854
|
+
}
|
|
3855
|
+
|
|
3856
|
+
return false;
|
|
3857
|
+
}
|
|
3858
|
+
|
|
3859
|
+
function readToken(forceRegexp) {
|
|
3860
|
+
if (!forceRegexp) tokStart = tokPos;
|
|
3861
|
+
else tokPos = tokStart + 1;
|
|
3862
|
+
if (options.locations) tokStartLoc = new Position;
|
|
3863
|
+
if (forceRegexp) return readRegexp();
|
|
3864
|
+
if (tokPos >= inputLen) return finishToken(_eof);
|
|
3865
|
+
|
|
3866
|
+
var code = input.charCodeAt(tokPos);
|
|
3867
|
+
|
|
3868
|
+
if (inTemplate) return getTemplateToken(code);
|
|
3869
|
+
|
|
3870
|
+
// Identifier or keyword. '\uXXXX' sequences are allowed in
|
|
3871
|
+
// identifiers, so '\' also dispatches to that.
|
|
3872
|
+
if (isIdentifierStart(code) || code === 92 /* '\' */) return readWord();
|
|
3873
|
+
|
|
3874
|
+
var tok = getTokenFromCode(code);
|
|
3875
|
+
|
|
3876
|
+
if (tok === false) {
|
|
3877
|
+
// If we are here, we either found a non-ASCII identifier
|
|
3878
|
+
// character, or something that's entirely disallowed.
|
|
3879
|
+
var ch = String.fromCharCode(code);
|
|
3880
|
+
if (ch === "\\" || nonASCIIidentifierStart.test(ch)) return readWord();
|
|
3881
|
+
raise(tokPos, "Unexpected character '" + ch + "'");
|
|
3882
|
+
}
|
|
3883
|
+
return tok;
|
|
3884
|
+
}
|
|
3885
|
+
|
|
3886
|
+
function finishOp(type, size) {
|
|
3887
|
+
var str = input.slice(tokPos, tokPos + size);
|
|
3888
|
+
tokPos += size;
|
|
3889
|
+
finishToken(type, str);
|
|
3890
|
+
}
|
|
3891
|
+
|
|
3892
|
+
// Parse a regular expression. Some context-awareness is necessary,
|
|
3893
|
+
// since a '/' inside a '[]' set does not end the expression.
|
|
3894
|
+
|
|
3895
|
+
function readRegexp() {
|
|
3896
|
+
var content = "", escaped, inClass, start = tokPos;
|
|
3897
|
+
for (;;) {
|
|
3898
|
+
if (tokPos >= inputLen) raise(start, "Unterminated regular expression");
|
|
3899
|
+
var ch = input.charAt(tokPos);
|
|
3900
|
+
if (newline.test(ch)) raise(start, "Unterminated regular expression");
|
|
3901
|
+
if (!escaped) {
|
|
3902
|
+
if (ch === "[") inClass = true;
|
|
3903
|
+
else if (ch === "]" && inClass) inClass = false;
|
|
3904
|
+
else if (ch === "/" && !inClass) break;
|
|
3905
|
+
escaped = ch === "\\";
|
|
3906
|
+
} else escaped = false;
|
|
3907
|
+
++tokPos;
|
|
3908
|
+
}
|
|
3909
|
+
var content = input.slice(start, tokPos);
|
|
3910
|
+
++tokPos;
|
|
3911
|
+
// Need to use `readWord1` because '\uXXXX' sequences are allowed
|
|
3912
|
+
// here (don't ask).
|
|
3913
|
+
var mods = readWord1();
|
|
3914
|
+
if (mods && !/^[gmsiy]*$/.test(mods)) raise(start, "Invalid regular expression flag");
|
|
3915
|
+
try {
|
|
3916
|
+
var value = new RegExp(content, mods);
|
|
3917
|
+
} catch (e) {
|
|
3918
|
+
if (e instanceof SyntaxError) raise(start, "Error parsing regular expression: " + e.message);
|
|
3919
|
+
raise(e);
|
|
3920
|
+
}
|
|
3921
|
+
return finishToken(_regexp, value);
|
|
3922
|
+
}
|
|
3923
|
+
|
|
3924
|
+
// Read an integer in the given radix. Return null if zero digits
|
|
3925
|
+
// were read, the integer value otherwise. When `len` is given, this
|
|
3926
|
+
// will return `null` unless the integer has exactly `len` digits.
|
|
3927
|
+
|
|
3928
|
+
function readInt(radix, len) {
|
|
3929
|
+
var start = tokPos, total = 0;
|
|
3930
|
+
for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {
|
|
3931
|
+
var code = input.charCodeAt(tokPos), val;
|
|
3932
|
+
if (code >= 97) val = code - 97 + 10; // a
|
|
3933
|
+
else if (code >= 65) val = code - 65 + 10; // A
|
|
3934
|
+
else if (code >= 48 && code <= 57) val = code - 48; // 0-9
|
|
3935
|
+
else val = Infinity;
|
|
3936
|
+
if (val >= radix) break;
|
|
3937
|
+
++tokPos;
|
|
3938
|
+
total = total * radix + val;
|
|
3939
|
+
}
|
|
3940
|
+
if (tokPos === start || len != null && tokPos - start !== len) return null;
|
|
3941
|
+
|
|
3942
|
+
return total;
|
|
3943
|
+
}
|
|
3944
|
+
|
|
3945
|
+
function readRadixNumber(radix) {
|
|
3946
|
+
tokPos += 2; // 0x
|
|
3947
|
+
var val = readInt(radix);
|
|
3948
|
+
if (val == null) raise(tokStart + 2, "Expected number in radix " + radix);
|
|
3949
|
+
if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number");
|
|
3950
|
+
return finishToken(_num, val);
|
|
3951
|
+
}
|
|
3952
|
+
|
|
3953
|
+
// Read an integer, octal integer, or floating-point number.
|
|
3954
|
+
|
|
3955
|
+
function readNumber(startsWithDot) {
|
|
3956
|
+
var start = tokPos, isFloat = false, octal = input.charCodeAt(tokPos) === 48;
|
|
3957
|
+
if (!startsWithDot && readInt(10) === null) raise(start, "Invalid number");
|
|
3958
|
+
if (input.charCodeAt(tokPos) === 46) {
|
|
3959
|
+
++tokPos;
|
|
3960
|
+
readInt(10);
|
|
3961
|
+
isFloat = true;
|
|
3962
|
+
}
|
|
3963
|
+
var next = input.charCodeAt(tokPos);
|
|
3964
|
+
if (next === 69 || next === 101) { // 'eE'
|
|
3965
|
+
next = input.charCodeAt(++tokPos);
|
|
3966
|
+
if (next === 43 || next === 45) ++tokPos; // '+-'
|
|
3967
|
+
if (readInt(10) === null) raise(start, "Invalid number");
|
|
3968
|
+
isFloat = true;
|
|
3969
|
+
}
|
|
3970
|
+
if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, "Identifier directly after number");
|
|
3971
|
+
|
|
3972
|
+
var str = input.slice(start, tokPos), val;
|
|
3973
|
+
if (isFloat) val = parseFloat(str);
|
|
3974
|
+
else if (!octal || str.length === 1) val = parseInt(str, 10);
|
|
3975
|
+
else if (/[89]/.test(str) || strict) raise(start, "Invalid number");
|
|
3976
|
+
else val = parseInt(str, 8);
|
|
3977
|
+
return finishToken(_num, val);
|
|
3978
|
+
}
|
|
3979
|
+
|
|
3980
|
+
// Read a string value, interpreting backslash-escapes.
|
|
3981
|
+
|
|
3982
|
+
function readCodePoint() {
|
|
3983
|
+
var ch = input.charCodeAt(tokPos), code;
|
|
3984
|
+
|
|
3985
|
+
if (ch === 123) {
|
|
3986
|
+
if (options.ecmaVersion < 6) unexpected();
|
|
3987
|
+
++tokPos;
|
|
3988
|
+
code = readHexChar(input.indexOf('}', tokPos) - tokPos);
|
|
3989
|
+
++tokPos;
|
|
3990
|
+
if (code > 0x10FFFF) unexpected();
|
|
3991
|
+
} else {
|
|
3992
|
+
code = readHexChar(4);
|
|
3993
|
+
}
|
|
3994
|
+
|
|
3995
|
+
// UTF-16 Encoding
|
|
3996
|
+
if (code <= 0xFFFF) {
|
|
3997
|
+
return String.fromCharCode(code);
|
|
3998
|
+
}
|
|
3999
|
+
var cu1 = ((code - 0x10000) >> 10) + 0xD800;
|
|
4000
|
+
var cu2 = ((code - 0x10000) & 1023) + 0xDC00;
|
|
4001
|
+
return String.fromCharCode(cu1, cu2);
|
|
4002
|
+
}
|
|
4003
|
+
|
|
4004
|
+
function readString(quote) {
|
|
4005
|
+
++tokPos;
|
|
4006
|
+
var out = "";
|
|
4007
|
+
for (;;) {
|
|
4008
|
+
if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant");
|
|
4009
|
+
var ch = input.charCodeAt(tokPos);
|
|
4010
|
+
if (ch === quote) {
|
|
4011
|
+
++tokPos;
|
|
4012
|
+
return finishToken(_string, out);
|
|
4013
|
+
}
|
|
4014
|
+
if (ch === 92) { // '\'
|
|
4015
|
+
out += readEscapedChar();
|
|
4016
|
+
} else {
|
|
4017
|
+
++tokPos;
|
|
4018
|
+
if (newline.test(String.fromCharCode(ch))) {
|
|
4019
|
+
raise(tokStart, "Unterminated string constant");
|
|
4020
|
+
}
|
|
4021
|
+
out += String.fromCharCode(ch); // '\'
|
|
4022
|
+
}
|
|
4023
|
+
}
|
|
4024
|
+
}
|
|
4025
|
+
|
|
4026
|
+
function readTmplString() {
|
|
4027
|
+
var out = "";
|
|
4028
|
+
for (;;) {
|
|
4029
|
+
if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant");
|
|
4030
|
+
var ch = input.charCodeAt(tokPos);
|
|
4031
|
+
if (ch === 96 || ch === 36 && input.charCodeAt(tokPos + 1) === 123) // '`', '${'
|
|
4032
|
+
return finishToken(_string, out);
|
|
4033
|
+
if (ch === 92) { // '\'
|
|
4034
|
+
out += readEscapedChar();
|
|
4035
|
+
} else {
|
|
4036
|
+
++tokPos;
|
|
4037
|
+
if (newline.test(String.fromCharCode(ch))) {
|
|
4038
|
+
if (ch === 13 && input.charCodeAt(tokPos) === 10) {
|
|
4039
|
+
++tokPos;
|
|
4040
|
+
ch = 10;
|
|
4041
|
+
}
|
|
4042
|
+
if (options.locations) {
|
|
4043
|
+
++tokCurLine;
|
|
4044
|
+
tokLineStart = tokPos;
|
|
4045
|
+
}
|
|
4046
|
+
}
|
|
4047
|
+
out += String.fromCharCode(ch); // '\'
|
|
4048
|
+
}
|
|
4049
|
+
}
|
|
4050
|
+
}
|
|
4051
|
+
|
|
4052
|
+
// Used to read escaped characters
|
|
4053
|
+
|
|
4054
|
+
function readEscapedChar() {
|
|
4055
|
+
var ch = input.charCodeAt(++tokPos);
|
|
4056
|
+
var octal = /^[0-7]+/.exec(input.slice(tokPos, tokPos + 3));
|
|
4057
|
+
if (octal) octal = octal[0];
|
|
4058
|
+
while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, -1);
|
|
4059
|
+
if (octal === "0") octal = null;
|
|
4060
|
+
++tokPos;
|
|
4061
|
+
if (octal) {
|
|
4062
|
+
if (strict) raise(tokPos - 2, "Octal literal in strict mode");
|
|
4063
|
+
tokPos += octal.length - 1;
|
|
4064
|
+
return String.fromCharCode(parseInt(octal, 8));
|
|
4065
|
+
} else {
|
|
4066
|
+
switch (ch) {
|
|
4067
|
+
case 110: return "\n"; // 'n' -> '\n'
|
|
4068
|
+
case 114: return "\r"; // 'r' -> '\r'
|
|
4069
|
+
case 120: return String.fromCharCode(readHexChar(2)); // 'x'
|
|
4070
|
+
case 117: return readCodePoint(); // 'u'
|
|
4071
|
+
case 85: return String.fromCharCode(readHexChar(8)); // 'U'
|
|
4072
|
+
case 116: return "\t"; // 't' -> '\t'
|
|
4073
|
+
case 98: return "\b"; // 'b' -> '\b'
|
|
4074
|
+
case 118: return "\u000b"; // 'v' -> '\u000b'
|
|
4075
|
+
case 102: return "\f"; // 'f' -> '\f'
|
|
4076
|
+
case 48: return "\0"; // 0 -> '\0'
|
|
4077
|
+
case 13: if (input.charCodeAt(tokPos) === 10) ++tokPos; // '\r\n'
|
|
4078
|
+
case 10: // ' \n'
|
|
4079
|
+
if (options.locations) { tokLineStart = tokPos; ++tokCurLine; }
|
|
4080
|
+
return "";
|
|
4081
|
+
default: return String.fromCharCode(ch);
|
|
4082
|
+
}
|
|
4083
|
+
}
|
|
4084
|
+
}
|
|
4085
|
+
|
|
4086
|
+
// Used to read character escape sequences ('\x', '\u', '\U').
|
|
4087
|
+
|
|
4088
|
+
function readHexChar(len) {
|
|
4089
|
+
var n = readInt(16, len);
|
|
4090
|
+
if (n === null) raise(tokStart, "Bad character escape sequence");
|
|
4091
|
+
return n;
|
|
4092
|
+
}
|
|
4093
|
+
|
|
4094
|
+
// Used to signal to callers of `readWord1` whether the word
|
|
4095
|
+
// contained any escape sequences. This is needed because words with
|
|
4096
|
+
// escape sequences must not be interpreted as keywords.
|
|
4097
|
+
|
|
4098
|
+
var containsEsc;
|
|
4099
|
+
|
|
4100
|
+
// Read an identifier, and return it as a string. Sets `containsEsc`
|
|
4101
|
+
// to whether the word contained a '\u' escape.
|
|
4102
|
+
//
|
|
4103
|
+
// Only builds up the word character-by-character when it actually
|
|
4104
|
+
// containeds an escape, as a micro-optimization.
|
|
4105
|
+
|
|
4106
|
+
function readWord1() {
|
|
4107
|
+
containsEsc = false;
|
|
4108
|
+
var word, first = true, start = tokPos;
|
|
4109
|
+
for (;;) {
|
|
4110
|
+
var ch = input.charCodeAt(tokPos);
|
|
4111
|
+
if (isIdentifierChar(ch)) {
|
|
4112
|
+
if (containsEsc) word += input.charAt(tokPos);
|
|
4113
|
+
++tokPos;
|
|
4114
|
+
} else if (ch === 92) { // "\"
|
|
4115
|
+
if (!containsEsc) word = input.slice(start, tokPos);
|
|
4116
|
+
containsEsc = true;
|
|
4117
|
+
if (input.charCodeAt(++tokPos) != 117) // "u"
|
|
4118
|
+
raise(tokPos, "Expecting Unicode escape sequence \\uXXXX");
|
|
4119
|
+
++tokPos;
|
|
4120
|
+
var esc = readHexChar(4);
|
|
4121
|
+
var escStr = String.fromCharCode(esc);
|
|
4122
|
+
if (!escStr) raise(tokPos - 1, "Invalid Unicode escape");
|
|
4123
|
+
if (!(first ? isIdentifierStart(esc) : isIdentifierChar(esc)))
|
|
4124
|
+
raise(tokPos - 4, "Invalid Unicode escape");
|
|
4125
|
+
word += escStr;
|
|
4126
|
+
} else {
|
|
4127
|
+
break;
|
|
4128
|
+
}
|
|
4129
|
+
first = false;
|
|
4130
|
+
}
|
|
4131
|
+
return containsEsc ? word : input.slice(start, tokPos);
|
|
4132
|
+
}
|
|
4133
|
+
|
|
4134
|
+
// Read an identifier or keyword token. Will check for reserved
|
|
4135
|
+
// words when necessary.
|
|
4136
|
+
|
|
4137
|
+
function readWord() {
|
|
4138
|
+
var word = readWord1();
|
|
4139
|
+
var type = _name;
|
|
4140
|
+
if (!containsEsc && isKeyword(word))
|
|
4141
|
+
type = keywordTypes[word];
|
|
4142
|
+
return finishToken(type, word);
|
|
4143
|
+
}
|
|
4144
|
+
|
|
4145
|
+
// ## Parser
|
|
4146
|
+
|
|
4147
|
+
// A recursive descent parser operates by defining functions for all
|
|
4148
|
+
// syntactic elements, and recursively calling those, each function
|
|
4149
|
+
// advancing the input stream and returning an AST node. Precedence
|
|
4150
|
+
// of constructs (for example, the fact that `!x[1]` means `!(x[1])`
|
|
4151
|
+
// instead of `(!x)[1]` is handled by the fact that the parser
|
|
4152
|
+
// function that parses unary prefix operators is called first, and
|
|
4153
|
+
// in turn calls the function that parses `[]` subscripts — that
|
|
4154
|
+
// way, it'll receive the node for `x[1]` already parsed, and wraps
|
|
4155
|
+
// *that* in the unary operator node.
|
|
4156
|
+
//
|
|
4157
|
+
// Acorn uses an [operator precedence parser][opp] to handle binary
|
|
4158
|
+
// operator precedence, because it is much more compact than using
|
|
4159
|
+
// the technique outlined above, which uses different, nesting
|
|
4160
|
+
// functions to specify precedence, for all of the ten binary
|
|
4161
|
+
// precedence levels that JavaScript defines.
|
|
4162
|
+
//
|
|
4163
|
+
// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser
|
|
4164
|
+
|
|
4165
|
+
// ### Parser utilities
|
|
4166
|
+
|
|
4167
|
+
// Continue to the next token.
|
|
4168
|
+
|
|
4169
|
+
function next() {
|
|
4170
|
+
lastStart = tokStart;
|
|
4171
|
+
lastEnd = tokEnd;
|
|
4172
|
+
lastEndLoc = tokEndLoc;
|
|
4173
|
+
readToken();
|
|
4174
|
+
}
|
|
4175
|
+
|
|
4176
|
+
// Enter strict mode. Re-reads the next token to please pedantic
|
|
4177
|
+
// tests ("use strict"; 010; -- should fail).
|
|
4178
|
+
|
|
4179
|
+
function setStrict(strct) {
|
|
4180
|
+
strict = strct;
|
|
4181
|
+
tokPos = tokStart;
|
|
4182
|
+
if (options.locations) {
|
|
4183
|
+
while (tokPos < tokLineStart) {
|
|
4184
|
+
tokLineStart = input.lastIndexOf("\n", tokLineStart - 2) + 1;
|
|
4185
|
+
--tokCurLine;
|
|
4186
|
+
}
|
|
4187
|
+
}
|
|
4188
|
+
skipSpace();
|
|
4189
|
+
readToken();
|
|
4190
|
+
}
|
|
4191
|
+
|
|
4192
|
+
// Start an AST node, attaching a start offset.
|
|
4193
|
+
|
|
4194
|
+
function Node() {
|
|
4195
|
+
this.type = null;
|
|
4196
|
+
this.start = tokStart;
|
|
4197
|
+
this.end = null;
|
|
4198
|
+
}
|
|
4199
|
+
|
|
4200
|
+
exports.Node = Node;
|
|
4201
|
+
|
|
4202
|
+
function SourceLocation() {
|
|
4203
|
+
this.start = tokStartLoc;
|
|
4204
|
+
this.end = null;
|
|
4205
|
+
if (sourceFile !== null) this.source = sourceFile;
|
|
4206
|
+
}
|
|
4207
|
+
|
|
4208
|
+
function startNode() {
|
|
4209
|
+
var node = new Node();
|
|
4210
|
+
if (options.locations)
|
|
4211
|
+
node.loc = new SourceLocation();
|
|
4212
|
+
if (options.directSourceFile)
|
|
4213
|
+
node.sourceFile = options.directSourceFile;
|
|
4214
|
+
if (options.ranges)
|
|
4215
|
+
node.range = [tokStart, 0];
|
|
4216
|
+
return node;
|
|
4217
|
+
}
|
|
4218
|
+
|
|
4219
|
+
// Start a node whose start offset information should be based on
|
|
4220
|
+
// the start of another node. For example, a binary operator node is
|
|
4221
|
+
// only started after its left-hand side has already been parsed.
|
|
4222
|
+
|
|
4223
|
+
function startNodeFrom(other) {
|
|
4224
|
+
var node = new Node();
|
|
4225
|
+
node.start = other.start;
|
|
4226
|
+
if (options.locations) {
|
|
4227
|
+
node.loc = new SourceLocation();
|
|
4228
|
+
node.loc.start = other.loc.start;
|
|
4229
|
+
}
|
|
4230
|
+
if (options.ranges)
|
|
4231
|
+
node.range = [other.range[0], 0];
|
|
4232
|
+
|
|
4233
|
+
return node;
|
|
4234
|
+
}
|
|
4235
|
+
|
|
4236
|
+
// Finish an AST node, adding `type` and `end` properties.
|
|
4237
|
+
|
|
4238
|
+
function finishNode(node, type) {
|
|
4239
|
+
node.type = type;
|
|
4240
|
+
node.end = lastEnd;
|
|
4241
|
+
if (options.locations)
|
|
4242
|
+
node.loc.end = lastEndLoc;
|
|
4243
|
+
if (options.ranges)
|
|
4244
|
+
node.range[1] = lastEnd;
|
|
4245
|
+
return node;
|
|
4246
|
+
}
|
|
4247
|
+
|
|
4248
|
+
// Test whether a statement node is the string literal `"use strict"`.
|
|
4249
|
+
|
|
4250
|
+
function isUseStrict(stmt) {
|
|
4251
|
+
return options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" &&
|
|
4252
|
+
stmt.expression.type === "Literal" && stmt.expression.value === "use strict";
|
|
4253
|
+
}
|
|
4254
|
+
|
|
4255
|
+
// Predicate that tests whether the next token is of the given
|
|
4256
|
+
// type, and if yes, consumes it as a side effect.
|
|
4257
|
+
|
|
4258
|
+
function eat(type) {
|
|
4259
|
+
if (tokType === type) {
|
|
4260
|
+
next();
|
|
4261
|
+
return true;
|
|
4262
|
+
} else {
|
|
4263
|
+
return false;
|
|
4264
|
+
}
|
|
4265
|
+
}
|
|
4266
|
+
|
|
4267
|
+
// Test whether a semicolon can be inserted at the current position.
|
|
4268
|
+
|
|
4269
|
+
function canInsertSemicolon() {
|
|
4270
|
+
return !options.strictSemicolons &&
|
|
4271
|
+
(tokType === _eof || tokType === _braceR || newline.test(input.slice(lastEnd, tokStart)));
|
|
4272
|
+
}
|
|
4273
|
+
|
|
4274
|
+
// Consume a semicolon, or, failing that, see if we are allowed to
|
|
4275
|
+
// pretend that there is a semicolon at this position.
|
|
4276
|
+
|
|
4277
|
+
function semicolon() {
|
|
4278
|
+
if (!eat(_semi) && !canInsertSemicolon()) unexpected();
|
|
4279
|
+
}
|
|
4280
|
+
|
|
4281
|
+
// Expect a token of a given type. If found, consume it, otherwise,
|
|
4282
|
+
// raise an unexpected token error.
|
|
4283
|
+
|
|
4284
|
+
function expect(type) {
|
|
4285
|
+
eat(type) || unexpected();
|
|
4286
|
+
}
|
|
4287
|
+
|
|
4288
|
+
// Raise an unexpected token error.
|
|
4289
|
+
|
|
4290
|
+
function unexpected(pos) {
|
|
4291
|
+
raise(pos != null ? pos : tokStart, "Unexpected token");
|
|
4292
|
+
}
|
|
4293
|
+
|
|
4294
|
+
// Checks if hash object has a property.
|
|
4295
|
+
|
|
4296
|
+
function has(obj, propName) {
|
|
4297
|
+
return Object.prototype.hasOwnProperty.call(obj, propName);
|
|
4298
|
+
}
|
|
4299
|
+
// Convert existing expression atom to assignable pattern
|
|
4300
|
+
// if possible.
|
|
4301
|
+
|
|
4302
|
+
function toAssignable(node, allowSpread, checkType) {
|
|
4303
|
+
if (options.ecmaVersion >= 6 && node) {
|
|
4304
|
+
switch (node.type) {
|
|
4305
|
+
case "Identifier":
|
|
4306
|
+
case "MemberExpression":
|
|
4307
|
+
break;
|
|
4308
|
+
|
|
4309
|
+
case "ObjectExpression":
|
|
4310
|
+
node.type = "ObjectPattern";
|
|
4311
|
+
for (var i = 0; i < node.properties.length; i++) {
|
|
4312
|
+
var prop = node.properties[i];
|
|
4313
|
+
if (prop.kind !== "init") unexpected(prop.key.start);
|
|
4314
|
+
toAssignable(prop.value, false, checkType);
|
|
4315
|
+
}
|
|
4316
|
+
break;
|
|
4317
|
+
|
|
4318
|
+
case "ArrayExpression":
|
|
4319
|
+
node.type = "ArrayPattern";
|
|
4320
|
+
for (var i = 0, lastI = node.elements.length - 1; i <= lastI; i++) {
|
|
4321
|
+
toAssignable(node.elements[i], i === lastI, checkType);
|
|
4322
|
+
}
|
|
4323
|
+
break;
|
|
4324
|
+
|
|
4325
|
+
case "SpreadElement":
|
|
4326
|
+
if (allowSpread) {
|
|
4327
|
+
toAssignable(node.argument, false, checkType);
|
|
4328
|
+
checkSpreadAssign(node.argument);
|
|
4329
|
+
} else {
|
|
4330
|
+
unexpected(node.start);
|
|
4331
|
+
}
|
|
4332
|
+
break;
|
|
4333
|
+
|
|
4334
|
+
default:
|
|
4335
|
+
if (checkType) unexpected(node.start);
|
|
4336
|
+
}
|
|
4337
|
+
}
|
|
4338
|
+
return node;
|
|
4339
|
+
}
|
|
4340
|
+
|
|
4341
|
+
// Checks if node can be assignable spread argument.
|
|
4342
|
+
|
|
4343
|
+
function checkSpreadAssign(node) {
|
|
4344
|
+
if (node.type !== "Identifier" && node.type !== "ArrayPattern")
|
|
4345
|
+
unexpected(node.start);
|
|
4346
|
+
}
|
|
4347
|
+
|
|
4348
|
+
// Verify that argument names are not repeated, and it does not
|
|
4349
|
+
// try to bind the words `eval` or `arguments`.
|
|
4350
|
+
|
|
4351
|
+
function checkFunctionParam(param, nameHash) {
|
|
4352
|
+
switch (param.type) {
|
|
4353
|
+
case "Identifier":
|
|
4354
|
+
if (isStrictReservedWord(param.name) || isStrictBadIdWord(param.name))
|
|
4355
|
+
raise(param.start, "Defining '" + param.name + "' in strict mode");
|
|
4356
|
+
if (has(nameHash, param.name))
|
|
4357
|
+
raise(param.start, "Argument name clash in strict mode");
|
|
4358
|
+
nameHash[param.name] = true;
|
|
4359
|
+
break;
|
|
4360
|
+
|
|
4361
|
+
case "ObjectPattern":
|
|
4362
|
+
for (var i = 0; i < param.properties.length; i++)
|
|
4363
|
+
checkFunctionParam(param.properties[i].value, nameHash);
|
|
4364
|
+
break;
|
|
4365
|
+
|
|
4366
|
+
case "ArrayPattern":
|
|
4367
|
+
for (var i = 0; i < param.elements.length; i++)
|
|
4368
|
+
checkFunctionParam(param.elements[i], nameHash);
|
|
4369
|
+
break;
|
|
4370
|
+
}
|
|
4371
|
+
}
|
|
4372
|
+
|
|
4373
|
+
// Check if property name clashes with already added.
|
|
4374
|
+
// Object/class getters and setters are not allowed to clash —
|
|
4375
|
+
// either with each other or with an init property — and in
|
|
4376
|
+
// strict mode, init properties are also not allowed to be repeated.
|
|
4377
|
+
|
|
4378
|
+
function checkPropClash(prop, propHash) {
|
|
4379
|
+
if (prop.computed) return;
|
|
4380
|
+
var key = prop.key, name;
|
|
4381
|
+
switch (key.type) {
|
|
4382
|
+
case "Identifier": name = key.name; break;
|
|
4383
|
+
case "Literal": name = String(key.value); break;
|
|
4384
|
+
default: return;
|
|
4385
|
+
}
|
|
4386
|
+
var kind = prop.kind || "init", other;
|
|
4387
|
+
if (has(propHash, name)) {
|
|
4388
|
+
other = propHash[name];
|
|
4389
|
+
var isGetSet = kind !== "init";
|
|
4390
|
+
if ((strict || isGetSet) && other[kind] || !(isGetSet ^ other.init))
|
|
4391
|
+
raise(key.start, "Redefinition of property");
|
|
4392
|
+
} else {
|
|
4393
|
+
other = propHash[name] = {
|
|
4394
|
+
init: false,
|
|
4395
|
+
get: false,
|
|
4396
|
+
set: false
|
|
4397
|
+
};
|
|
4398
|
+
}
|
|
4399
|
+
other[kind] = true;
|
|
4400
|
+
}
|
|
4401
|
+
|
|
4402
|
+
// Verify that a node is an lval — something that can be assigned
|
|
4403
|
+
// to.
|
|
4404
|
+
|
|
4405
|
+
function checkLVal(expr, isBinding) {
|
|
4406
|
+
switch (expr.type) {
|
|
4407
|
+
case "Identifier":
|
|
4408
|
+
if (strict && (isStrictBadIdWord(expr.name) || isStrictReservedWord(expr.name)))
|
|
4409
|
+
raise(expr.start, isBinding
|
|
4410
|
+
? "Binding " + expr.name + " in strict mode"
|
|
4411
|
+
: "Assigning to " + expr.name + " in strict mode"
|
|
4412
|
+
);
|
|
4413
|
+
break;
|
|
4414
|
+
|
|
4415
|
+
case "MemberExpression":
|
|
4416
|
+
if (!isBinding) break;
|
|
4417
|
+
|
|
4418
|
+
case "ObjectPattern":
|
|
4419
|
+
for (var i = 0; i < expr.properties.length; i++)
|
|
4420
|
+
checkLVal(expr.properties[i].value, isBinding);
|
|
4421
|
+
break;
|
|
4422
|
+
|
|
4423
|
+
case "ArrayPattern":
|
|
4424
|
+
for (var i = 0; i < expr.elements.length; i++) {
|
|
4425
|
+
var elem = expr.elements[i];
|
|
4426
|
+
if (elem) checkLVal(elem, isBinding);
|
|
4427
|
+
}
|
|
4428
|
+
break;
|
|
4429
|
+
|
|
4430
|
+
case "SpreadElement":
|
|
4431
|
+
break;
|
|
4432
|
+
|
|
4433
|
+
default:
|
|
4434
|
+
raise(expr.start, "Assigning to rvalue");
|
|
4435
|
+
}
|
|
4436
|
+
}
|
|
4437
|
+
|
|
4438
|
+
// ### Statement parsing
|
|
4439
|
+
|
|
4440
|
+
// Parse a program. Initializes the parser, reads any number of
|
|
4441
|
+
// statements, and wraps them in a Program node. Optionally takes a
|
|
4442
|
+
// `program` argument. If present, the statements will be appended
|
|
4443
|
+
// to its body instead of creating a new node.
|
|
4444
|
+
|
|
4445
|
+
function parseTopLevel(program) {
|
|
4446
|
+
var node = program || startNode(), first = true;
|
|
4447
|
+
if (!program) node.body = [];
|
|
4448
|
+
while (tokType !== _eof) {
|
|
4449
|
+
var stmt = parseStatement();
|
|
4450
|
+
node.body.push(stmt);
|
|
4451
|
+
if (first && isUseStrict(stmt)) setStrict(true);
|
|
4452
|
+
first = false;
|
|
4453
|
+
}
|
|
4454
|
+
return finishNode(node, "Program");
|
|
4455
|
+
}
|
|
4456
|
+
|
|
4457
|
+
var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"};
|
|
4458
|
+
|
|
4459
|
+
// Parse a single statement.
|
|
4460
|
+
//
|
|
4461
|
+
// If expecting a statement and finding a slash operator, parse a
|
|
4462
|
+
// regular expression literal. This is to handle cases like
|
|
4463
|
+
// `if (foo) /blah/.exec(foo);`, where looking at the previous token
|
|
4464
|
+
// does not help.
|
|
4465
|
+
|
|
4466
|
+
function parseStatement() {
|
|
4467
|
+
if (tokType === _slash || tokType === _assign && tokVal == "/=")
|
|
4468
|
+
readToken(true);
|
|
4469
|
+
|
|
4470
|
+
var starttype = tokType, node = startNode();
|
|
4471
|
+
|
|
4472
|
+
// Most types of statements are recognized by the keyword they
|
|
4473
|
+
// start with. Many are trivial to parse, some require a bit of
|
|
4474
|
+
// complexity.
|
|
4475
|
+
|
|
4476
|
+
switch (starttype) {
|
|
4477
|
+
case _break: case _continue: return parseBreakContinueStatement(node, starttype.keyword);
|
|
4478
|
+
case _debugger: return parseDebuggerStatement(node);
|
|
4479
|
+
case _do: return parseDoStatement(node);
|
|
4480
|
+
case _for: return parseForStatement(node);
|
|
4481
|
+
case _function: return parseFunctionStatement(node);
|
|
4482
|
+
case _class: return parseClass(node, true);
|
|
4483
|
+
case _if: return parseIfStatement(node);
|
|
4484
|
+
case _return: return parseReturnStatement(node);
|
|
4485
|
+
case _switch: return parseSwitchStatement(node);
|
|
4486
|
+
case _throw: return parseThrowStatement(node);
|
|
4487
|
+
case _try: return parseTryStatement(node);
|
|
4488
|
+
case _var: case _let: case _const: return parseVarStatement(node, starttype.keyword);
|
|
4489
|
+
case _while: return parseWhileStatement(node);
|
|
4490
|
+
case _with: return parseWithStatement(node);
|
|
4491
|
+
case _braceL: return parseBlock(); // no point creating a function for this
|
|
4492
|
+
case _semi: return parseEmptyStatement(node);
|
|
4493
|
+
case _export: return parseExport(node);
|
|
4494
|
+
case _import: return parseImport(node);
|
|
4495
|
+
|
|
4496
|
+
// If the statement does not start with a statement keyword or a
|
|
4497
|
+
// brace, it's an ExpressionStatement or LabeledStatement. We
|
|
4498
|
+
// simply start parsing an expression, and afterwards, if the
|
|
4499
|
+
// next token is a colon and the expression was a simple
|
|
4500
|
+
// Identifier node, we switch to interpreting it as a label.
|
|
4501
|
+
default:
|
|
4502
|
+
var maybeName = tokVal, expr = parseExpression();
|
|
4503
|
+
if (starttype === _name && expr.type === "Identifier" && eat(_colon))
|
|
4504
|
+
return parseLabeledStatement(node, maybeName, expr);
|
|
4505
|
+
else return parseExpressionStatement(node, expr);
|
|
4506
|
+
}
|
|
4507
|
+
}
|
|
4508
|
+
|
|
4509
|
+
function parseBreakContinueStatement(node, keyword) {
|
|
4510
|
+
var isBreak = keyword == "break";
|
|
4511
|
+
next();
|
|
4512
|
+
if (eat(_semi) || canInsertSemicolon()) node.label = null;
|
|
4513
|
+
else if (tokType !== _name) unexpected();
|
|
4514
|
+
else {
|
|
4515
|
+
node.label = parseIdent();
|
|
4516
|
+
semicolon();
|
|
4517
|
+
}
|
|
4518
|
+
|
|
4519
|
+
// Verify that there is an actual destination to break or
|
|
4520
|
+
// continue to.
|
|
4521
|
+
for (var i = 0; i < labels.length; ++i) {
|
|
4522
|
+
var lab = labels[i];
|
|
4523
|
+
if (node.label == null || lab.name === node.label.name) {
|
|
4524
|
+
if (lab.kind != null && (isBreak || lab.kind === "loop")) break;
|
|
4525
|
+
if (node.label && isBreak) break;
|
|
4526
|
+
}
|
|
4527
|
+
}
|
|
4528
|
+
if (i === labels.length) raise(node.start, "Unsyntactic " + keyword);
|
|
4529
|
+
return finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement");
|
|
4530
|
+
}
|
|
4531
|
+
|
|
4532
|
+
function parseDebuggerStatement(node) {
|
|
4533
|
+
next();
|
|
4534
|
+
semicolon();
|
|
4535
|
+
return finishNode(node, "DebuggerStatement");
|
|
4536
|
+
}
|
|
4537
|
+
|
|
4538
|
+
function parseDoStatement(node) {
|
|
4539
|
+
next();
|
|
4540
|
+
labels.push(loopLabel);
|
|
4541
|
+
node.body = parseStatement();
|
|
4542
|
+
labels.pop();
|
|
4543
|
+
expect(_while);
|
|
4544
|
+
node.test = parseParenExpression();
|
|
4545
|
+
semicolon();
|
|
4546
|
+
return finishNode(node, "DoWhileStatement");
|
|
4547
|
+
}
|
|
4548
|
+
|
|
4549
|
+
// Disambiguating between a `for` and a `for`/`in` or `for`/`of`
|
|
4550
|
+
// loop is non-trivial. Basically, we have to parse the init `var`
|
|
4551
|
+
// statement or expression, disallowing the `in` operator (see
|
|
4552
|
+
// the second parameter to `parseExpression`), and then check
|
|
4553
|
+
// whether the next token is `in` or `of`. When there is no init
|
|
4554
|
+
// part (semicolon immediately after the opening parenthesis), it
|
|
4555
|
+
// is a regular `for` loop.
|
|
4556
|
+
|
|
4557
|
+
function parseForStatement(node) {
|
|
4558
|
+
next();
|
|
4559
|
+
labels.push(loopLabel);
|
|
4560
|
+
expect(_parenL);
|
|
4561
|
+
if (tokType === _semi) return parseFor(node, null);
|
|
4562
|
+
if (tokType === _var || tokType === _let) {
|
|
4563
|
+
var init = startNode(), varKind = tokType.keyword, isLet = tokType === _let;
|
|
4564
|
+
next();
|
|
4565
|
+
parseVar(init, true, varKind);
|
|
4566
|
+
finishNode(init, "VariableDeclaration");
|
|
4567
|
+
if ((tokType === _in || (options.ecmaVersion >= 6 && tokType === _name && tokVal === "of")) && init.declarations.length === 1 &&
|
|
4568
|
+
!(isLet && init.declarations[0].init))
|
|
4569
|
+
return parseForIn(node, init);
|
|
4570
|
+
return parseFor(node, init);
|
|
4571
|
+
}
|
|
4572
|
+
var init = parseExpression(false, true);
|
|
4573
|
+
if (tokType === _in || (options.ecmaVersion >= 6 && tokType === _name && tokVal === "of")) {
|
|
4574
|
+
checkLVal(init);
|
|
4575
|
+
return parseForIn(node, init);
|
|
4576
|
+
}
|
|
4577
|
+
return parseFor(node, init);
|
|
4578
|
+
}
|
|
4579
|
+
|
|
4580
|
+
function parseFunctionStatement(node) {
|
|
4581
|
+
next();
|
|
4582
|
+
return parseFunction(node, true);
|
|
4583
|
+
}
|
|
4584
|
+
|
|
4585
|
+
function parseIfStatement(node) {
|
|
4586
|
+
next();
|
|
4587
|
+
node.test = parseParenExpression();
|
|
4588
|
+
node.consequent = parseStatement();
|
|
4589
|
+
node.alternate = eat(_else) ? parseStatement() : null;
|
|
4590
|
+
return finishNode(node, "IfStatement");
|
|
4591
|
+
}
|
|
4592
|
+
|
|
4593
|
+
function parseReturnStatement(node) {
|
|
4594
|
+
if (!inFunction && !options.allowReturnOutsideFunction)
|
|
4595
|
+
raise(tokStart, "'return' outside of function");
|
|
4596
|
+
next();
|
|
4597
|
+
|
|
4598
|
+
// In `return` (and `break`/`continue`), the keywords with
|
|
4599
|
+
// optional arguments, we eagerly look for a semicolon or the
|
|
4600
|
+
// possibility to insert one.
|
|
4601
|
+
|
|
4602
|
+
if (eat(_semi) || canInsertSemicolon()) node.argument = null;
|
|
4603
|
+
else { node.argument = parseExpression(); semicolon(); }
|
|
4604
|
+
return finishNode(node, "ReturnStatement");
|
|
4605
|
+
}
|
|
4606
|
+
|
|
4607
|
+
function parseSwitchStatement(node) {
|
|
4608
|
+
next();
|
|
4609
|
+
node.discriminant = parseParenExpression();
|
|
4610
|
+
node.cases = [];
|
|
4611
|
+
expect(_braceL);
|
|
4612
|
+
labels.push(switchLabel);
|
|
4613
|
+
|
|
4614
|
+
// Statements under must be grouped (by label) in SwitchCase
|
|
4615
|
+
// nodes. `cur` is used to keep the node that we are currently
|
|
4616
|
+
// adding statements to.
|
|
4617
|
+
|
|
4618
|
+
for (var cur, sawDefault; tokType != _braceR;) {
|
|
4619
|
+
if (tokType === _case || tokType === _default) {
|
|
4620
|
+
var isCase = tokType === _case;
|
|
4621
|
+
if (cur) finishNode(cur, "SwitchCase");
|
|
4622
|
+
node.cases.push(cur = startNode());
|
|
4623
|
+
cur.consequent = [];
|
|
4624
|
+
next();
|
|
4625
|
+
if (isCase) cur.test = parseExpression();
|
|
4626
|
+
else {
|
|
4627
|
+
if (sawDefault) raise(lastStart, "Multiple default clauses"); sawDefault = true;
|
|
4628
|
+
cur.test = null;
|
|
4629
|
+
}
|
|
4630
|
+
expect(_colon);
|
|
4631
|
+
} else {
|
|
4632
|
+
if (!cur) unexpected();
|
|
4633
|
+
cur.consequent.push(parseStatement());
|
|
4634
|
+
}
|
|
4635
|
+
}
|
|
4636
|
+
if (cur) finishNode(cur, "SwitchCase");
|
|
4637
|
+
next(); // Closing brace
|
|
4638
|
+
labels.pop();
|
|
4639
|
+
return finishNode(node, "SwitchStatement");
|
|
4640
|
+
}
|
|
4641
|
+
|
|
4642
|
+
function parseThrowStatement(node) {
|
|
4643
|
+
next();
|
|
4644
|
+
if (newline.test(input.slice(lastEnd, tokStart)))
|
|
4645
|
+
raise(lastEnd, "Illegal newline after throw");
|
|
4646
|
+
node.argument = parseExpression();
|
|
4647
|
+
semicolon();
|
|
4648
|
+
return finishNode(node, "ThrowStatement");
|
|
4649
|
+
}
|
|
4650
|
+
|
|
4651
|
+
function parseTryStatement(node) {
|
|
4652
|
+
next();
|
|
4653
|
+
node.block = parseBlock();
|
|
4654
|
+
node.handler = null;
|
|
4655
|
+
if (tokType === _catch) {
|
|
4656
|
+
var clause = startNode();
|
|
4657
|
+
next();
|
|
4658
|
+
expect(_parenL);
|
|
4659
|
+
clause.param = parseIdent();
|
|
4660
|
+
if (strict && isStrictBadIdWord(clause.param.name))
|
|
4661
|
+
raise(clause.param.start, "Binding " + clause.param.name + " in strict mode");
|
|
4662
|
+
expect(_parenR);
|
|
4663
|
+
clause.guard = null;
|
|
4664
|
+
clause.body = parseBlock();
|
|
4665
|
+
node.handler = finishNode(clause, "CatchClause");
|
|
4666
|
+
}
|
|
4667
|
+
node.guardedHandlers = empty;
|
|
4668
|
+
node.finalizer = eat(_finally) ? parseBlock() : null;
|
|
4669
|
+
if (!node.handler && !node.finalizer)
|
|
4670
|
+
raise(node.start, "Missing catch or finally clause");
|
|
4671
|
+
return finishNode(node, "TryStatement");
|
|
4672
|
+
}
|
|
4673
|
+
|
|
4674
|
+
function parseVarStatement(node, kind) {
|
|
4675
|
+
next();
|
|
4676
|
+
parseVar(node, false, kind);
|
|
4677
|
+
semicolon();
|
|
4678
|
+
return finishNode(node, "VariableDeclaration");
|
|
4679
|
+
}
|
|
4680
|
+
|
|
4681
|
+
function parseWhileStatement(node) {
|
|
4682
|
+
next();
|
|
4683
|
+
node.test = parseParenExpression();
|
|
4684
|
+
labels.push(loopLabel);
|
|
4685
|
+
node.body = parseStatement();
|
|
4686
|
+
labels.pop();
|
|
4687
|
+
return finishNode(node, "WhileStatement");
|
|
4688
|
+
}
|
|
4689
|
+
|
|
4690
|
+
function parseWithStatement(node) {
|
|
4691
|
+
if (strict) raise(tokStart, "'with' in strict mode");
|
|
4692
|
+
next();
|
|
4693
|
+
node.object = parseParenExpression();
|
|
4694
|
+
node.body = parseStatement();
|
|
4695
|
+
return finishNode(node, "WithStatement");
|
|
4696
|
+
}
|
|
4697
|
+
|
|
4698
|
+
function parseEmptyStatement(node) {
|
|
4699
|
+
next();
|
|
4700
|
+
return finishNode(node, "EmptyStatement");
|
|
4701
|
+
}
|
|
4702
|
+
|
|
4703
|
+
function parseLabeledStatement(node, maybeName, expr) {
|
|
4704
|
+
for (var i = 0; i < labels.length; ++i)
|
|
4705
|
+
if (labels[i].name === maybeName) raise(expr.start, "Label '" + maybeName + "' is already declared");
|
|
4706
|
+
var kind = tokType.isLoop ? "loop" : tokType === _switch ? "switch" : null;
|
|
4707
|
+
labels.push({name: maybeName, kind: kind});
|
|
4708
|
+
node.body = parseStatement();
|
|
4709
|
+
labels.pop();
|
|
4710
|
+
node.label = expr;
|
|
4711
|
+
return finishNode(node, "LabeledStatement");
|
|
4712
|
+
}
|
|
4713
|
+
|
|
4714
|
+
function parseExpressionStatement(node, expr) {
|
|
4715
|
+
node.expression = expr;
|
|
4716
|
+
semicolon();
|
|
4717
|
+
return finishNode(node, "ExpressionStatement");
|
|
4718
|
+
}
|
|
4719
|
+
|
|
4720
|
+
// Used for constructs like `switch` and `if` that insist on
|
|
4721
|
+
// parentheses around their expression.
|
|
4722
|
+
|
|
4723
|
+
function parseParenExpression() {
|
|
4724
|
+
expect(_parenL);
|
|
4725
|
+
var val = parseExpression();
|
|
4726
|
+
expect(_parenR);
|
|
4727
|
+
return val;
|
|
4728
|
+
}
|
|
4729
|
+
|
|
4730
|
+
// Parse a semicolon-enclosed block of statements, handling `"use
|
|
4731
|
+
// strict"` declarations when `allowStrict` is true (used for
|
|
4732
|
+
// function bodies).
|
|
4733
|
+
|
|
4734
|
+
function parseBlock(allowStrict) {
|
|
4735
|
+
var node = startNode(), first = true, oldStrict;
|
|
4736
|
+
node.body = [];
|
|
4737
|
+
expect(_braceL);
|
|
4738
|
+
while (!eat(_braceR)) {
|
|
4739
|
+
var stmt = parseStatement();
|
|
4740
|
+
node.body.push(stmt);
|
|
4741
|
+
if (first && allowStrict && isUseStrict(stmt)) {
|
|
4742
|
+
oldStrict = strict;
|
|
4743
|
+
setStrict(strict = true);
|
|
4744
|
+
}
|
|
4745
|
+
first = false;
|
|
4746
|
+
}
|
|
4747
|
+
if (oldStrict === false) setStrict(false);
|
|
4748
|
+
return finishNode(node, "BlockStatement");
|
|
4749
|
+
}
|
|
4750
|
+
|
|
4751
|
+
// Parse a regular `for` loop. The disambiguation code in
|
|
4752
|
+
// `parseStatement` will already have parsed the init statement or
|
|
4753
|
+
// expression.
|
|
4754
|
+
|
|
4755
|
+
function parseFor(node, init) {
|
|
4756
|
+
node.init = init;
|
|
4757
|
+
expect(_semi);
|
|
4758
|
+
node.test = tokType === _semi ? null : parseExpression();
|
|
4759
|
+
expect(_semi);
|
|
4760
|
+
node.update = tokType === _parenR ? null : parseExpression();
|
|
4761
|
+
expect(_parenR);
|
|
4762
|
+
node.body = parseStatement();
|
|
4763
|
+
labels.pop();
|
|
4764
|
+
return finishNode(node, "ForStatement");
|
|
4765
|
+
}
|
|
4766
|
+
|
|
4767
|
+
// Parse a `for`/`in` and `for`/`of` loop, which are almost
|
|
4768
|
+
// same from parser's perspective.
|
|
4769
|
+
|
|
4770
|
+
function parseForIn(node, init) {
|
|
4771
|
+
var type = tokType === _in ? "ForInStatement" : "ForOfStatement";
|
|
4772
|
+
next();
|
|
4773
|
+
node.left = init;
|
|
4774
|
+
node.right = parseExpression();
|
|
4775
|
+
expect(_parenR);
|
|
4776
|
+
node.body = parseStatement();
|
|
4777
|
+
labels.pop();
|
|
4778
|
+
return finishNode(node, type);
|
|
4779
|
+
}
|
|
4780
|
+
|
|
4781
|
+
// Parse a list of variable declarations.
|
|
4782
|
+
|
|
4783
|
+
function parseVar(node, noIn, kind) {
|
|
4784
|
+
node.declarations = [];
|
|
4785
|
+
node.kind = kind;
|
|
4786
|
+
for (;;) {
|
|
4787
|
+
var decl = startNode();
|
|
4788
|
+
decl.id = options.ecmaVersion >= 6 ? toAssignable(parseExprAtom()) : parseIdent();
|
|
4789
|
+
checkLVal(decl.id, true);
|
|
4790
|
+
decl.init = eat(_eq) ? parseExpression(true, noIn) : (kind === _const.keyword ? unexpected() : null);
|
|
4791
|
+
node.declarations.push(finishNode(decl, "VariableDeclarator"));
|
|
4792
|
+
if (!eat(_comma)) break;
|
|
4793
|
+
}
|
|
4794
|
+
return node;
|
|
4795
|
+
}
|
|
4796
|
+
|
|
4797
|
+
// ### Expression parsing
|
|
4798
|
+
|
|
4799
|
+
// These nest, from the most general expression type at the top to
|
|
4800
|
+
// 'atomic', nondivisible expression types at the bottom. Most of
|
|
4801
|
+
// the functions will simply let the function(s) below them parse,
|
|
4802
|
+
// and, *if* the syntactic construct they handle is present, wrap
|
|
4803
|
+
// the AST node that the inner parser gave them in another node.
|
|
4804
|
+
|
|
4805
|
+
// Parse a full expression. The arguments are used to forbid comma
|
|
4806
|
+
// sequences (in argument lists, array literals, or object literals)
|
|
4807
|
+
// or the `in` operator (in for loops initalization expressions).
|
|
4808
|
+
|
|
4809
|
+
function parseExpression(noComma, noIn) {
|
|
4810
|
+
var expr = parseMaybeAssign(noIn);
|
|
4811
|
+
if (!noComma && tokType === _comma) {
|
|
4812
|
+
var node = startNodeFrom(expr);
|
|
4813
|
+
node.expressions = [expr];
|
|
4814
|
+
while (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn));
|
|
4815
|
+
return finishNode(node, "SequenceExpression");
|
|
4816
|
+
}
|
|
4817
|
+
return expr;
|
|
4818
|
+
}
|
|
4819
|
+
|
|
4820
|
+
// Parse an assignment expression. This includes applications of
|
|
4821
|
+
// operators like `+=`.
|
|
4822
|
+
|
|
4823
|
+
function parseMaybeAssign(noIn) {
|
|
4824
|
+
var left = parseMaybeConditional(noIn);
|
|
4825
|
+
if (tokType.isAssign) {
|
|
4826
|
+
var node = startNodeFrom(left);
|
|
4827
|
+
node.operator = tokVal;
|
|
4828
|
+
node.left = tokType === _eq ? toAssignable(left) : left;
|
|
4829
|
+
checkLVal(left);
|
|
4830
|
+
next();
|
|
4831
|
+
node.right = parseMaybeAssign(noIn);
|
|
4832
|
+
return finishNode(node, "AssignmentExpression");
|
|
4833
|
+
}
|
|
4834
|
+
return left;
|
|
4835
|
+
}
|
|
4836
|
+
|
|
4837
|
+
// Parse a ternary conditional (`?:`) operator.
|
|
4838
|
+
|
|
4839
|
+
function parseMaybeConditional(noIn) {
|
|
4840
|
+
var expr = parseExprOps(noIn);
|
|
4841
|
+
if (eat(_question)) {
|
|
4842
|
+
var node = startNodeFrom(expr);
|
|
4843
|
+
node.test = expr;
|
|
4844
|
+
node.consequent = parseExpression(true);
|
|
4845
|
+
expect(_colon);
|
|
4846
|
+
node.alternate = parseExpression(true, noIn);
|
|
4847
|
+
return finishNode(node, "ConditionalExpression");
|
|
4848
|
+
}
|
|
4849
|
+
return expr;
|
|
4850
|
+
}
|
|
4851
|
+
|
|
4852
|
+
// Start the precedence parser.
|
|
4853
|
+
|
|
4854
|
+
function parseExprOps(noIn) {
|
|
4855
|
+
return parseExprOp(parseMaybeUnary(), -1, noIn);
|
|
4856
|
+
}
|
|
4857
|
+
|
|
4858
|
+
// Parse binary operators with the operator precedence parsing
|
|
4859
|
+
// algorithm. `left` is the left-hand side of the operator.
|
|
4860
|
+
// `minPrec` provides context that allows the function to stop and
|
|
4861
|
+
// defer further parser to one of its callers when it encounters an
|
|
4862
|
+
// operator that has a lower precedence than the set it is parsing.
|
|
4863
|
+
|
|
4864
|
+
function parseExprOp(left, minPrec, noIn) {
|
|
4865
|
+
var prec = tokType.binop;
|
|
4866
|
+
if (prec != null && (!noIn || tokType !== _in)) {
|
|
4867
|
+
if (prec > minPrec) {
|
|
4868
|
+
var node = startNodeFrom(left);
|
|
4869
|
+
node.left = left;
|
|
4870
|
+
node.operator = tokVal;
|
|
4871
|
+
var op = tokType;
|
|
4872
|
+
next();
|
|
4873
|
+
node.right = parseExprOp(parseMaybeUnary(), prec, noIn);
|
|
4874
|
+
var exprNode = finishNode(node, (op === _logicalOR || op === _logicalAND) ? "LogicalExpression" : "BinaryExpression");
|
|
4875
|
+
return parseExprOp(exprNode, minPrec, noIn);
|
|
4876
|
+
}
|
|
4877
|
+
}
|
|
4878
|
+
return left;
|
|
4879
|
+
}
|
|
4880
|
+
|
|
4881
|
+
// Parse unary operators, both prefix and postfix.
|
|
4882
|
+
|
|
4883
|
+
function parseMaybeUnary() {
|
|
4884
|
+
if (tokType.prefix) {
|
|
4885
|
+
var node = startNode(), update = tokType.isUpdate;
|
|
4886
|
+
node.operator = tokVal;
|
|
4887
|
+
node.prefix = true;
|
|
4888
|
+
tokRegexpAllowed = true;
|
|
4889
|
+
next();
|
|
4890
|
+
node.argument = parseMaybeUnary();
|
|
4891
|
+
if (update) checkLVal(node.argument);
|
|
4892
|
+
else if (strict && node.operator === "delete" &&
|
|
4893
|
+
node.argument.type === "Identifier")
|
|
4894
|
+
raise(node.start, "Deleting local variable in strict mode");
|
|
4895
|
+
return finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
|
|
4896
|
+
}
|
|
4897
|
+
var expr = parseExprSubscripts();
|
|
4898
|
+
while (tokType.postfix && !canInsertSemicolon()) {
|
|
4899
|
+
var node = startNodeFrom(expr);
|
|
4900
|
+
node.operator = tokVal;
|
|
4901
|
+
node.prefix = false;
|
|
4902
|
+
node.argument = expr;
|
|
4903
|
+
checkLVal(expr);
|
|
4904
|
+
next();
|
|
4905
|
+
expr = finishNode(node, "UpdateExpression");
|
|
4906
|
+
}
|
|
4907
|
+
return expr;
|
|
4908
|
+
}
|
|
4909
|
+
|
|
4910
|
+
// Parse call, dot, and `[]`-subscript expressions.
|
|
4911
|
+
|
|
4912
|
+
function parseExprSubscripts() {
|
|
4913
|
+
return parseSubscripts(parseExprAtom());
|
|
4914
|
+
}
|
|
4915
|
+
|
|
4916
|
+
function parseSubscripts(base, noCalls) {
|
|
4917
|
+
if (eat(_dot)) {
|
|
4918
|
+
var node = startNodeFrom(base);
|
|
4919
|
+
node.object = base;
|
|
4920
|
+
node.property = parseIdent(true);
|
|
4921
|
+
node.computed = false;
|
|
4922
|
+
return parseSubscripts(finishNode(node, "MemberExpression"), noCalls);
|
|
4923
|
+
} else if (eat(_bracketL)) {
|
|
4924
|
+
var node = startNodeFrom(base);
|
|
4925
|
+
node.object = base;
|
|
4926
|
+
node.property = parseExpression();
|
|
4927
|
+
node.computed = true;
|
|
4928
|
+
expect(_bracketR);
|
|
4929
|
+
return parseSubscripts(finishNode(node, "MemberExpression"), noCalls);
|
|
4930
|
+
} else if (!noCalls && eat(_parenL)) {
|
|
4931
|
+
var node = startNodeFrom(base);
|
|
4932
|
+
node.callee = base;
|
|
4933
|
+
node.arguments = parseExprList(_parenR, false);
|
|
4934
|
+
return parseSubscripts(finishNode(node, "CallExpression"), noCalls);
|
|
4935
|
+
} else if (tokType === _bquote) {
|
|
4936
|
+
var node = startNodeFrom(base);
|
|
4937
|
+
node.tag = base;
|
|
4938
|
+
node.quasi = parseTemplate();
|
|
4939
|
+
return parseSubscripts(finishNode(node, "TaggedTemplateExpression"), noCalls);
|
|
4940
|
+
} return base;
|
|
4941
|
+
}
|
|
4942
|
+
|
|
4943
|
+
// Parse an atomic expression — either a single token that is an
|
|
4944
|
+
// expression, an expression started by a keyword like `function` or
|
|
4945
|
+
// `new`, or an expression wrapped in punctuation like `()`, `[]`,
|
|
4946
|
+
// or `{}`.
|
|
4947
|
+
|
|
4948
|
+
function parseExprAtom() {
|
|
4949
|
+
switch (tokType) {
|
|
4950
|
+
case _this:
|
|
4951
|
+
var node = startNode();
|
|
4952
|
+
next();
|
|
4953
|
+
return finishNode(node, "ThisExpression");
|
|
4954
|
+
|
|
4955
|
+
case _yield:
|
|
4956
|
+
if (inGenerator) return parseYield();
|
|
4957
|
+
|
|
4958
|
+
case _name:
|
|
4959
|
+
var id = parseIdent(tokType !== _name);
|
|
4960
|
+
if (eat(_arrow)) {
|
|
4961
|
+
return parseArrowExpression(startNodeFrom(id), [id]);
|
|
4962
|
+
}
|
|
4963
|
+
return id;
|
|
4964
|
+
|
|
4965
|
+
case _num: case _string: case _regexp:
|
|
4966
|
+
var node = startNode();
|
|
4967
|
+
node.value = tokVal;
|
|
4968
|
+
node.raw = input.slice(tokStart, tokEnd);
|
|
4969
|
+
next();
|
|
4970
|
+
return finishNode(node, "Literal");
|
|
4971
|
+
|
|
4972
|
+
case _null: case _true: case _false:
|
|
4973
|
+
var node = startNode();
|
|
4974
|
+
node.value = tokType.atomValue;
|
|
4975
|
+
node.raw = tokType.keyword;
|
|
4976
|
+
next();
|
|
4977
|
+
return finishNode(node, "Literal");
|
|
4978
|
+
|
|
4979
|
+
case _parenL:
|
|
4980
|
+
var tokStartLoc1 = tokStartLoc, tokStart1 = tokStart, val, exprList;
|
|
4981
|
+
next();
|
|
4982
|
+
// check whether this is generator comprehension or regular expression
|
|
4983
|
+
if (options.ecmaVersion >= 6 && tokType === _for) {
|
|
4984
|
+
val = parseComprehension(startNode(), true);
|
|
4985
|
+
} else {
|
|
4986
|
+
var oldParenL = ++metParenL;
|
|
4987
|
+
if (tokType !== _parenR) {
|
|
4988
|
+
val = parseExpression();
|
|
4989
|
+
exprList = val.type === "SequenceExpression" ? val.expressions : [val];
|
|
4990
|
+
} else {
|
|
4991
|
+
exprList = [];
|
|
4992
|
+
}
|
|
4993
|
+
expect(_parenR);
|
|
4994
|
+
// if '=>' follows '(...)', convert contents to arguments
|
|
4995
|
+
if (metParenL === oldParenL && eat(_arrow)) {
|
|
4996
|
+
val = parseArrowExpression(startNode(), exprList);
|
|
4997
|
+
} else {
|
|
4998
|
+
// forbid '()' before everything but '=>'
|
|
4999
|
+
if (!val) unexpected(lastStart);
|
|
5000
|
+
// forbid '...' in sequence expressions
|
|
5001
|
+
if (options.ecmaVersion >= 6) {
|
|
5002
|
+
for (var i = 0; i < exprList.length; i++) {
|
|
5003
|
+
if (exprList[i].type === "SpreadElement") unexpected();
|
|
5004
|
+
}
|
|
5005
|
+
}
|
|
5006
|
+
}
|
|
5007
|
+
}
|
|
5008
|
+
val.start = tokStart1;
|
|
5009
|
+
val.end = lastEnd;
|
|
5010
|
+
if (options.locations) {
|
|
5011
|
+
val.loc.start = tokStartLoc1;
|
|
5012
|
+
val.loc.end = lastEndLoc;
|
|
5013
|
+
}
|
|
5014
|
+
if (options.ranges) {
|
|
5015
|
+
val.range = [tokStart1, lastEnd];
|
|
5016
|
+
}
|
|
5017
|
+
return val;
|
|
5018
|
+
|
|
5019
|
+
case _bracketL:
|
|
5020
|
+
var node = startNode();
|
|
5021
|
+
next();
|
|
5022
|
+
// check whether this is array comprehension or regular array
|
|
5023
|
+
if (options.ecmaVersion >= 6 && tokType === _for) {
|
|
5024
|
+
return parseComprehension(node, false);
|
|
5025
|
+
}
|
|
5026
|
+
node.elements = parseExprList(_bracketR, true, true);
|
|
5027
|
+
return finishNode(node, "ArrayExpression");
|
|
5028
|
+
|
|
5029
|
+
case _braceL:
|
|
5030
|
+
return parseObj();
|
|
5031
|
+
|
|
5032
|
+
case _function:
|
|
5033
|
+
var node = startNode();
|
|
5034
|
+
next();
|
|
5035
|
+
return parseFunction(node, false);
|
|
5036
|
+
|
|
5037
|
+
case _class:
|
|
5038
|
+
return parseClass(startNode(), false);
|
|
5039
|
+
|
|
5040
|
+
case _new:
|
|
5041
|
+
return parseNew();
|
|
5042
|
+
|
|
5043
|
+
case _ellipsis:
|
|
5044
|
+
return parseSpread();
|
|
5045
|
+
|
|
5046
|
+
case _bquote:
|
|
5047
|
+
return parseTemplate();
|
|
5048
|
+
|
|
5049
|
+
default:
|
|
5050
|
+
unexpected();
|
|
5051
|
+
}
|
|
5052
|
+
}
|
|
5053
|
+
|
|
5054
|
+
// New's precedence is slightly tricky. It must allow its argument
|
|
5055
|
+
// to be a `[]` or dot subscript expression, but not a call — at
|
|
5056
|
+
// least, not without wrapping it in parentheses. Thus, it uses the
|
|
5057
|
+
|
|
5058
|
+
function parseNew() {
|
|
5059
|
+
var node = startNode();
|
|
5060
|
+
next();
|
|
5061
|
+
node.callee = parseSubscripts(parseExprAtom(), true);
|
|
5062
|
+
if (eat(_parenL)) node.arguments = parseExprList(_parenR, false);
|
|
5063
|
+
else node.arguments = empty;
|
|
5064
|
+
return finishNode(node, "NewExpression");
|
|
5065
|
+
}
|
|
5066
|
+
|
|
5067
|
+
// Parse spread element '...expr'
|
|
2614
5068
|
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
5069
|
+
function parseSpread() {
|
|
5070
|
+
var node = startNode();
|
|
5071
|
+
next();
|
|
5072
|
+
node.argument = parseExpression(true);
|
|
5073
|
+
return finishNode(node, "SpreadElement");
|
|
5074
|
+
}
|
|
2618
5075
|
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
5076
|
+
// Parse template expression.
|
|
5077
|
+
|
|
5078
|
+
function parseTemplate() {
|
|
5079
|
+
var node = startNode();
|
|
5080
|
+
node.expressions = [];
|
|
5081
|
+
node.quasis = [];
|
|
5082
|
+
inTemplate = true;
|
|
5083
|
+
next();
|
|
5084
|
+
for (;;) {
|
|
5085
|
+
var elem = startNode();
|
|
5086
|
+
elem.value = {cooked: tokVal, raw: input.slice(tokStart, tokEnd)};
|
|
5087
|
+
elem.tail = false;
|
|
5088
|
+
next();
|
|
5089
|
+
node.quasis.push(finishNode(elem, "TemplateElement"));
|
|
5090
|
+
if (tokType === _bquote) { // '`', end of template
|
|
5091
|
+
elem.tail = true;
|
|
5092
|
+
break;
|
|
5093
|
+
}
|
|
5094
|
+
inTemplate = false;
|
|
5095
|
+
expect(_dollarBraceL);
|
|
5096
|
+
node.expressions.push(parseExpression());
|
|
5097
|
+
inTemplate = true;
|
|
5098
|
+
// hack to include previously skipped space
|
|
5099
|
+
tokPos = tokEnd;
|
|
5100
|
+
expect(_braceR);
|
|
5101
|
+
}
|
|
5102
|
+
inTemplate = false;
|
|
5103
|
+
next();
|
|
5104
|
+
return finishNode(node, "TemplateLiteral");
|
|
5105
|
+
}
|
|
2622
5106
|
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
5107
|
+
// Parse an object literal.
|
|
5108
|
+
|
|
5109
|
+
function parseObj() {
|
|
5110
|
+
var node = startNode(), first = true, propHash = {};
|
|
5111
|
+
node.properties = [];
|
|
5112
|
+
next();
|
|
5113
|
+
while (!eat(_braceR)) {
|
|
5114
|
+
if (!first) {
|
|
5115
|
+
expect(_comma);
|
|
5116
|
+
if (options.allowTrailingCommas && eat(_braceR)) break;
|
|
5117
|
+
} else first = false;
|
|
5118
|
+
|
|
5119
|
+
var prop = startNode(), isGenerator;
|
|
5120
|
+
if (options.ecmaVersion >= 6) {
|
|
5121
|
+
prop.method = false;
|
|
5122
|
+
prop.shorthand = false;
|
|
5123
|
+
isGenerator = eat(_star);
|
|
5124
|
+
}
|
|
5125
|
+
parsePropertyName(prop);
|
|
5126
|
+
if (eat(_colon)) {
|
|
5127
|
+
prop.value = parseExpression(true);
|
|
5128
|
+
prop.kind = "init";
|
|
5129
|
+
} else if (options.ecmaVersion >= 6 && tokType === _parenL) {
|
|
5130
|
+
prop.kind = "init";
|
|
5131
|
+
prop.method = true;
|
|
5132
|
+
prop.value = parseMethod(isGenerator);
|
|
5133
|
+
} else if (options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
|
|
5134
|
+
(prop.key.name === "get" || prop.key.name === "set")) {
|
|
5135
|
+
if (isGenerator) unexpected();
|
|
5136
|
+
prop.kind = prop.key.name;
|
|
5137
|
+
parsePropertyName(prop);
|
|
5138
|
+
prop.value = parseMethod(false);
|
|
5139
|
+
} else if (options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
|
|
5140
|
+
prop.kind = "init";
|
|
5141
|
+
prop.value = prop.key;
|
|
5142
|
+
prop.shorthand = true;
|
|
5143
|
+
} else unexpected();
|
|
5144
|
+
|
|
5145
|
+
checkPropClash(prop, propHash);
|
|
5146
|
+
node.properties.push(finishNode(prop, "Property"));
|
|
5147
|
+
}
|
|
5148
|
+
return finishNode(node, "ObjectExpression");
|
|
5149
|
+
}
|
|
2626
5150
|
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
5151
|
+
function parsePropertyName(prop) {
|
|
5152
|
+
if (options.ecmaVersion >= 6) {
|
|
5153
|
+
if (eat(_bracketL)) {
|
|
5154
|
+
prop.computed = true;
|
|
5155
|
+
prop.key = parseExpression();
|
|
5156
|
+
expect(_bracketR);
|
|
5157
|
+
return;
|
|
5158
|
+
} else {
|
|
5159
|
+
prop.computed = false;
|
|
5160
|
+
}
|
|
2631
5161
|
}
|
|
2632
|
-
|
|
2633
|
-
}
|
|
5162
|
+
prop.key = (tokType === _num || tokType === _string) ? parseExprAtom() : parseIdent(true);
|
|
5163
|
+
}
|
|
2634
5164
|
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
5165
|
+
// Initialize empty function node.
|
|
5166
|
+
|
|
5167
|
+
function initFunction(node) {
|
|
5168
|
+
node.id = null;
|
|
5169
|
+
node.params = [];
|
|
5170
|
+
if (options.ecmaVersion >= 6) {
|
|
5171
|
+
node.defaults = [];
|
|
5172
|
+
node.rest = null;
|
|
5173
|
+
node.generator = false;
|
|
2642
5174
|
}
|
|
2643
|
-
|
|
2644
|
-
};
|
|
5175
|
+
}
|
|
2645
5176
|
|
|
2646
|
-
|
|
5177
|
+
// Parse a function declaration or literal (depending on the
|
|
5178
|
+
// `isStatement` parameter).
|
|
2647
5179
|
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
5180
|
+
function parseFunction(node, isStatement, allowExpressionBody) {
|
|
5181
|
+
initFunction(node);
|
|
5182
|
+
if (options.ecmaVersion >= 6) {
|
|
5183
|
+
node.generator = eat(_star);
|
|
5184
|
+
}
|
|
5185
|
+
if (isStatement || tokType === _name) {
|
|
5186
|
+
node.id = parseIdent();
|
|
5187
|
+
}
|
|
5188
|
+
parseFunctionParams(node);
|
|
5189
|
+
parseFunctionBody(node, allowExpressionBody);
|
|
5190
|
+
return finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
|
|
5191
|
+
}
|
|
2652
5192
|
|
|
2653
|
-
|
|
5193
|
+
// Parse object or class method.
|
|
2654
5194
|
|
|
2655
|
-
|
|
2656
|
-
var
|
|
2657
|
-
|
|
2658
|
-
|
|
5195
|
+
function parseMethod(isGenerator) {
|
|
5196
|
+
var node = startNode();
|
|
5197
|
+
initFunction(node);
|
|
5198
|
+
parseFunctionParams(node);
|
|
5199
|
+
var allowExpressionBody;
|
|
5200
|
+
if (options.ecmaVersion >= 6) {
|
|
5201
|
+
node.generator = isGenerator;
|
|
5202
|
+
allowExpressionBody = true;
|
|
5203
|
+
} else {
|
|
5204
|
+
allowExpressionBody = false;
|
|
5205
|
+
}
|
|
5206
|
+
parseFunctionBody(node, allowExpressionBody);
|
|
5207
|
+
return finishNode(node, "FunctionExpression");
|
|
5208
|
+
}
|
|
2659
5209
|
|
|
2660
|
-
|
|
2661
|
-
setupScopeAndReferences: setupScopeAndReferences,
|
|
2662
|
-
isReference: isReference,
|
|
2663
|
-
};
|
|
5210
|
+
// Parse arrow function expression with given parameters.
|
|
2664
5211
|
|
|
2665
|
-
function
|
|
2666
|
-
|
|
2667
|
-
createTopScope(root.$scope);
|
|
2668
|
-
}
|
|
5212
|
+
function parseArrowExpression(node, params) {
|
|
5213
|
+
initFunction(node);
|
|
2669
5214
|
|
|
2670
|
-
|
|
2671
|
-
node.$parent = parent;
|
|
2672
|
-
node.$scope = parent ? parent.$scope : null; // may be overridden
|
|
5215
|
+
var defaults = node.defaults, hasDefaults = false;
|
|
2673
5216
|
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
node.$scope = new Scope({
|
|
2677
|
-
kind: "block",
|
|
2678
|
-
node: node,
|
|
2679
|
-
parent: parent.$scope,
|
|
2680
|
-
});
|
|
5217
|
+
for (var i = 0, lastI = params.length - 1; i <= lastI; i++) {
|
|
5218
|
+
var param = params[i];
|
|
2681
5219
|
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
5220
|
+
if (param.type === "AssignmentExpression" && param.operator === "=") {
|
|
5221
|
+
hasDefaults = true;
|
|
5222
|
+
params[i] = param.left;
|
|
5223
|
+
defaults.push(param.right);
|
|
5224
|
+
} else {
|
|
5225
|
+
toAssignable(param, i === lastI, true);
|
|
5226
|
+
defaults.push(null);
|
|
5227
|
+
if (param.type === "SpreadElement") {
|
|
5228
|
+
params.length--;
|
|
5229
|
+
node.rest = param.argument;
|
|
5230
|
+
break;
|
|
5231
|
+
}
|
|
5232
|
+
}
|
|
5233
|
+
}
|
|
2688
5234
|
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
// There's no block-scope under it
|
|
5235
|
+
node.params = params;
|
|
5236
|
+
if (!hasDefaults) node.defaults = [];
|
|
2692
5237
|
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
parent: parent.$scope,
|
|
2697
|
-
});
|
|
5238
|
+
parseFunctionBody(node, true);
|
|
5239
|
+
return finishNode(node, "ArrowFunctionExpression");
|
|
5240
|
+
}
|
|
2698
5241
|
|
|
2699
|
-
|
|
2700
|
-
if (node.id) {
|
|
2701
|
-
if (node.type === "FunctionDeclaration") {
|
|
2702
|
-
// Function name goes in parent scope for declared functions
|
|
2703
|
-
parent.$scope.add(node.id.name, "fun", node.id, null);
|
|
2704
|
-
} else if (node.type === "FunctionExpression") {
|
|
2705
|
-
// Function name goes in function's scope for named function expressions
|
|
2706
|
-
node.$scope.add(node.id.name, "fun", node.id, null);
|
|
2707
|
-
} else {
|
|
2708
|
-
assert(false);
|
|
2709
|
-
}
|
|
2710
|
-
}
|
|
5242
|
+
// Parse function parameters.
|
|
2711
5243
|
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
});
|
|
5244
|
+
function parseFunctionParams(node) {
|
|
5245
|
+
var defaults = [], hasDefaults = false;
|
|
2715
5246
|
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
5247
|
+
expect(_parenL);
|
|
5248
|
+
for (;;) {
|
|
5249
|
+
if (eat(_parenR)) {
|
|
5250
|
+
break;
|
|
5251
|
+
} else if (options.ecmaVersion >= 6 && eat(_ellipsis)) {
|
|
5252
|
+
node.rest = toAssignable(parseExprAtom(), false, true);
|
|
5253
|
+
checkSpreadAssign(node.rest);
|
|
5254
|
+
expect(_parenR);
|
|
5255
|
+
defaults.push(null);
|
|
5256
|
+
break;
|
|
5257
|
+
} else {
|
|
5258
|
+
node.params.push(options.ecmaVersion >= 6 ? toAssignable(parseExprAtom(), false, true) : parseIdent());
|
|
5259
|
+
if (options.ecmaVersion >= 6) {
|
|
5260
|
+
if (eat(_eq)) {
|
|
5261
|
+
hasDefaults = true;
|
|
5262
|
+
defaults.push(parseExpression(true));
|
|
5263
|
+
} else {
|
|
5264
|
+
defaults.push(null);
|
|
5265
|
+
}
|
|
5266
|
+
}
|
|
5267
|
+
if (!eat(_comma)) {
|
|
5268
|
+
expect(_parenR);
|
|
5269
|
+
break;
|
|
5270
|
+
}
|
|
5271
|
+
}
|
|
5272
|
+
}
|
|
2724
5273
|
|
|
2725
|
-
|
|
2726
|
-
|
|
5274
|
+
if (hasDefaults) node.defaults = defaults;
|
|
5275
|
+
}
|
|
2727
5276
|
|
|
2728
|
-
|
|
2729
|
-
kind: "catch-block",
|
|
2730
|
-
node: node,
|
|
2731
|
-
parent: parent.$scope,
|
|
2732
|
-
});
|
|
2733
|
-
node.$scope.add(identifier.name, "caught", identifier, null);
|
|
5277
|
+
// Parse function body and check parameters.
|
|
2734
5278
|
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
// This is used to mark "taint" the name since adding a new variable in the scope,
|
|
2738
|
-
// with a propagated name, would change the meaning of the existing references.
|
|
2739
|
-
//
|
|
2740
|
-
// catch(e) is special because even though e is a variable in its own scope,
|
|
2741
|
-
// we want to make sure that catch(e){let e} is never transformed to
|
|
2742
|
-
// catch(e){var e} (but rather var e$0). For that reason we taint the use of e
|
|
2743
|
-
// in the closest hoist-scope, i.e. where var e$0 belongs.
|
|
2744
|
-
node.$scope.closestHoistScope().markPropagates(identifier.name);
|
|
5279
|
+
function parseFunctionBody(node, allowExpression) {
|
|
5280
|
+
var isExpression = allowExpression && tokType !== _braceL;
|
|
2745
5281
|
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
5282
|
+
if (isExpression) {
|
|
5283
|
+
node.body = parseExpression(true);
|
|
5284
|
+
node.expression = true;
|
|
5285
|
+
} else {
|
|
5286
|
+
// Start a new scope with regard to labels and the `inFunction`
|
|
5287
|
+
// flag (restore them to their old value afterwards).
|
|
5288
|
+
var oldInFunc = inFunction, oldInGen = inGenerator, oldLabels = labels;
|
|
5289
|
+
inFunction = true; inGenerator = node.generator; labels = [];
|
|
5290
|
+
node.body = parseBlock(true);
|
|
5291
|
+
node.expression = false;
|
|
5292
|
+
inFunction = oldInFunc; inGenerator = oldInGen; labels = oldLabels;
|
|
5293
|
+
}
|
|
5294
|
+
|
|
5295
|
+
// If this is a strict mode function, verify that argument names
|
|
5296
|
+
// are not repeated, and it does not try to bind the words `eval`
|
|
5297
|
+
// or `arguments`.
|
|
5298
|
+
if (strict || !isExpression && node.body.body.length && isUseStrict(node.body.body[0])) {
|
|
5299
|
+
var nameHash = {};
|
|
5300
|
+
if (node.id)
|
|
5301
|
+
checkFunctionParam(node.id, {});
|
|
5302
|
+
for (var i = 0; i < node.params.length; i++)
|
|
5303
|
+
checkFunctionParam(node.params[i], nameHash);
|
|
5304
|
+
if (node.rest)
|
|
5305
|
+
checkFunctionParam(node.rest, nameHash);
|
|
2754
5306
|
}
|
|
2755
|
-
}
|
|
5307
|
+
}
|
|
2756
5308
|
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
5309
|
+
// Parse a class declaration or literal (depending on the
|
|
5310
|
+
// `isStatement` parameter).
|
|
5311
|
+
|
|
5312
|
+
function parseClass(node, isStatement) {
|
|
5313
|
+
next();
|
|
5314
|
+
node.id = tokType === _name ? parseIdent() : isStatement ? unexpected() : null;
|
|
5315
|
+
node.superClass = eat(_extends) ? parseExpression() : null;
|
|
5316
|
+
var classBody = startNode(), methodHash = {}, staticMethodHash = {};
|
|
5317
|
+
classBody.body = [];
|
|
5318
|
+
expect(_braceL);
|
|
5319
|
+
while (!eat(_braceR)) {
|
|
5320
|
+
var method = startNode();
|
|
5321
|
+
if (tokType === _name && tokVal === "static") {
|
|
5322
|
+
next();
|
|
5323
|
+
method['static'] = true;
|
|
5324
|
+
} else {
|
|
5325
|
+
method['static'] = false;
|
|
5326
|
+
}
|
|
5327
|
+
var isGenerator = eat(_star);
|
|
5328
|
+
parsePropertyName(method);
|
|
5329
|
+
if (tokType === _name && !method.computed && method.key.type === "Identifier" &&
|
|
5330
|
+
(method.key.name === "get" || method.key.name === "set")) {
|
|
5331
|
+
if (isGenerator) unexpected();
|
|
5332
|
+
method.kind = method.key.name;
|
|
5333
|
+
parsePropertyName(method);
|
|
5334
|
+
} else {
|
|
5335
|
+
method.kind = "";
|
|
5336
|
+
}
|
|
5337
|
+
method.value = parseMethod(isGenerator);
|
|
5338
|
+
checkPropClash(method, method['static'] ? staticMethodHash : methodHash);
|
|
5339
|
+
classBody.body.push(finishNode(method, "MethodDefinition"));
|
|
5340
|
+
eat(_semi);
|
|
2767
5341
|
}
|
|
5342
|
+
node.body = finishNode(classBody, "ClassBody");
|
|
5343
|
+
return finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression");
|
|
5344
|
+
}
|
|
2768
5345
|
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
5346
|
+
// Parses a comma-separated list of expressions, and returns them as
|
|
5347
|
+
// an array. `close` is the token type that ends the list, and
|
|
5348
|
+
// `allowEmpty` can be turned on to allow subsequent commas with
|
|
5349
|
+
// nothing in between them to be parsed as `null` (which is needed
|
|
5350
|
+
// for array literals).
|
|
2774
5351
|
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
5352
|
+
function parseExprList(close, allowTrailingComma, allowEmpty) {
|
|
5353
|
+
var elts = [], first = true;
|
|
5354
|
+
while (!eat(close)) {
|
|
5355
|
+
if (!first) {
|
|
5356
|
+
expect(_comma);
|
|
5357
|
+
if (allowTrailingComma && options.allowTrailingCommas && eat(close)) break;
|
|
5358
|
+
} else first = false;
|
|
2780
5359
|
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
5360
|
+
if (allowEmpty && tokType === _comma) elts.push(null);
|
|
5361
|
+
else elts.push(parseExpression(true));
|
|
5362
|
+
}
|
|
5363
|
+
return elts;
|
|
5364
|
+
}
|
|
2784
5365
|
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
5366
|
+
// Parse the next token as an identifier. If `liberal` is true (used
|
|
5367
|
+
// when parsing properties), it will also convert keywords into
|
|
5368
|
+
// identifiers.
|
|
5369
|
+
|
|
5370
|
+
function parseIdent(liberal) {
|
|
5371
|
+
var node = startNode();
|
|
5372
|
+
if (liberal && options.forbidReserved == "everywhere") liberal = false;
|
|
5373
|
+
if (tokType === _name) {
|
|
5374
|
+
if (!liberal &&
|
|
5375
|
+
(options.forbidReserved &&
|
|
5376
|
+
(options.ecmaVersion === 3 ? isReservedWord3 : isReservedWord5)(tokVal) ||
|
|
5377
|
+
strict && isStrictReservedWord(tokVal)) &&
|
|
5378
|
+
input.slice(tokStart, tokEnd).indexOf("\\") == -1)
|
|
5379
|
+
raise(tokStart, "The keyword '" + tokVal + "' is reserved");
|
|
5380
|
+
node.name = tokVal;
|
|
5381
|
+
} else if (liberal && tokType.keyword) {
|
|
5382
|
+
node.name = tokType.keyword;
|
|
5383
|
+
} else {
|
|
5384
|
+
unexpected();
|
|
5385
|
+
}
|
|
5386
|
+
tokRegexpAllowed = false;
|
|
5387
|
+
next();
|
|
5388
|
+
return finishNode(node, "Identifier");
|
|
5389
|
+
}
|
|
2788
5390
|
|
|
2789
|
-
|
|
2790
|
-
|
|
5391
|
+
// Parses module export declaration.
|
|
5392
|
+
|
|
5393
|
+
function parseExport(node) {
|
|
5394
|
+
next();
|
|
5395
|
+
// export var|const|let|function|class ...;
|
|
5396
|
+
if (tokType === _var || tokType === _const || tokType === _let || tokType === _function || tokType === _class) {
|
|
5397
|
+
node.declaration = parseStatement();
|
|
5398
|
+
node['default'] = false;
|
|
5399
|
+
node.specifiers = null;
|
|
5400
|
+
node.source = null;
|
|
5401
|
+
} else
|
|
5402
|
+
// export default ...;
|
|
5403
|
+
if (eat(_default)) {
|
|
5404
|
+
node.declaration = parseExpression(true);
|
|
5405
|
+
node['default'] = true;
|
|
5406
|
+
node.specifiers = null;
|
|
5407
|
+
node.source = null;
|
|
5408
|
+
semicolon();
|
|
5409
|
+
} else {
|
|
5410
|
+
// export * from '...'
|
|
5411
|
+
// export { x, y as z } [from '...']
|
|
5412
|
+
var isBatch = tokType === _star;
|
|
5413
|
+
node.declaration = null;
|
|
5414
|
+
node['default'] = false;
|
|
5415
|
+
node.specifiers = parseExportSpecifiers();
|
|
5416
|
+
if (tokType === _name && tokVal === "from") {
|
|
5417
|
+
next();
|
|
5418
|
+
node.source = tokType === _string ? parseExprAtom() : unexpected();
|
|
5419
|
+
} else {
|
|
5420
|
+
if (isBatch) unexpected();
|
|
5421
|
+
node.source = null;
|
|
5422
|
+
}
|
|
5423
|
+
}
|
|
5424
|
+
return finishNode(node, "ExportDeclaration");
|
|
5425
|
+
}
|
|
2791
5426
|
|
|
2792
|
-
|
|
2793
|
-
return kind === "const" || kind === "let";
|
|
2794
|
-
}
|
|
5427
|
+
// Parses a comma-separated list of module exports.
|
|
2795
5428
|
|
|
2796
|
-
function
|
|
2797
|
-
|
|
2798
|
-
|
|
5429
|
+
function parseExportSpecifiers() {
|
|
5430
|
+
var nodes = [], first = true;
|
|
5431
|
+
if (tokType === _star) {
|
|
5432
|
+
// export * from '...'
|
|
5433
|
+
var node = startNode();
|
|
5434
|
+
next();
|
|
5435
|
+
nodes.push(finishNode(node, "ExportBatchSpecifier"));
|
|
5436
|
+
} else {
|
|
5437
|
+
// export { x, y as z } [from '...']
|
|
5438
|
+
expect(_braceL);
|
|
5439
|
+
while (!eat(_braceR)) {
|
|
5440
|
+
if (!first) {
|
|
5441
|
+
expect(_comma);
|
|
5442
|
+
if (options.allowTrailingCommas && eat(_braceR)) break;
|
|
5443
|
+
} else first = false;
|
|
5444
|
+
|
|
5445
|
+
var node = startNode();
|
|
5446
|
+
node.id = parseIdent();
|
|
5447
|
+
if (tokType === _name && tokVal === "as") {
|
|
5448
|
+
next();
|
|
5449
|
+
node.name = parseIdent(true);
|
|
5450
|
+
} else {
|
|
5451
|
+
node.name = null;
|
|
5452
|
+
}
|
|
5453
|
+
nodes.push(finishNode(node, "ExportSpecifier"));
|
|
5454
|
+
}
|
|
5455
|
+
}
|
|
5456
|
+
return nodes;
|
|
5457
|
+
}
|
|
2799
5458
|
|
|
2800
|
-
|
|
2801
|
-
return node.type === "ForStatement" && node.init && node.init.type === "VariableDeclaration" && isConstLet(node.init.kind);
|
|
2802
|
-
}
|
|
5459
|
+
// Parses import declaration.
|
|
2803
5460
|
|
|
2804
|
-
function
|
|
2805
|
-
|
|
2806
|
-
|
|
5461
|
+
function parseImport(node) {
|
|
5462
|
+
next();
|
|
5463
|
+
// import '...';
|
|
5464
|
+
if (tokType === _string) {
|
|
5465
|
+
node.specifiers = [];
|
|
5466
|
+
node.source = parseExprAtom();
|
|
5467
|
+
node.kind = "";
|
|
5468
|
+
} else {
|
|
5469
|
+
node.specifiers = parseImportSpecifiers();
|
|
5470
|
+
if (tokType !== _name || tokVal !== "from") unexpected();
|
|
5471
|
+
next();
|
|
5472
|
+
node.source = tokType === _string ? parseExprAtom() : unexpected();
|
|
5473
|
+
// only for backward compatibility with Esprima's AST
|
|
5474
|
+
// (it doesn't support mixed default + named yet)
|
|
5475
|
+
node.kind = node.specifiers[0]['default'] ? "default" : "named";
|
|
5476
|
+
}
|
|
5477
|
+
return finishNode(node, "ImportDeclaration");
|
|
5478
|
+
}
|
|
2807
5479
|
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
5480
|
+
// Parses a comma-separated list of module imports.
|
|
5481
|
+
|
|
5482
|
+
function parseImportSpecifiers() {
|
|
5483
|
+
var nodes = [], first = true;
|
|
5484
|
+
if (tokType === _star) {
|
|
5485
|
+
var node = startNode();
|
|
5486
|
+
next();
|
|
5487
|
+
if (tokType !== _name || tokVal !== "as") unexpected();
|
|
5488
|
+
next();
|
|
5489
|
+
node.name = parseIdent();
|
|
5490
|
+
checkLVal(node.name, true);
|
|
5491
|
+
nodes.push(finishNode(node, "ImportBatchSpecifier"));
|
|
5492
|
+
return nodes;
|
|
5493
|
+
}
|
|
5494
|
+
if (tokType === _name) {
|
|
5495
|
+
// import defaultObj, { x, y as z } from '...'
|
|
5496
|
+
var node = startNode();
|
|
5497
|
+
node.id = parseIdent();
|
|
5498
|
+
checkLVal(node.id, true);
|
|
5499
|
+
node.name = null;
|
|
5500
|
+
node['default'] = true;
|
|
5501
|
+
nodes.push(finishNode(node, "ImportSpecifier"));
|
|
5502
|
+
if (!eat(_comma)) return nodes;
|
|
5503
|
+
}
|
|
5504
|
+
expect(_braceL);
|
|
5505
|
+
while (!eat(_braceR)) {
|
|
5506
|
+
if (!first) {
|
|
5507
|
+
expect(_comma);
|
|
5508
|
+
if (options.allowTrailingCommas && eat(_braceR)) break;
|
|
5509
|
+
} else first = false;
|
|
5510
|
+
|
|
5511
|
+
var node = startNode();
|
|
5512
|
+
node.id = parseIdent(true);
|
|
5513
|
+
if (tokType === _name && tokVal === "as") {
|
|
5514
|
+
next();
|
|
5515
|
+
node.name = parseIdent();
|
|
5516
|
+
} else {
|
|
5517
|
+
node.name = null;
|
|
5518
|
+
}
|
|
5519
|
+
checkLVal(node.name || node.id, true);
|
|
5520
|
+
node['default'] = false;
|
|
5521
|
+
nodes.push(finishNode(node, "ImportSpecifier"));
|
|
5522
|
+
}
|
|
5523
|
+
return nodes;
|
|
5524
|
+
}
|
|
2811
5525
|
|
|
2812
|
-
|
|
2813
|
-
return node.type === "FunctionDeclaration" || node.type === "FunctionExpression";
|
|
2814
|
-
}
|
|
5526
|
+
// Parses yield expression inside generator.
|
|
2815
5527
|
|
|
2816
|
-
function
|
|
2817
|
-
var
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
5528
|
+
function parseYield() {
|
|
5529
|
+
var node = startNode();
|
|
5530
|
+
next();
|
|
5531
|
+
if (eat(_semi) || canInsertSemicolon()) {
|
|
5532
|
+
node.delegate = false;
|
|
5533
|
+
node.argument = null;
|
|
5534
|
+
} else {
|
|
5535
|
+
node.delegate = eat(_star);
|
|
5536
|
+
node.argument = parseExpression(true);
|
|
5537
|
+
}
|
|
5538
|
+
return finishNode(node, "YieldExpression");
|
|
5539
|
+
}
|
|
5540
|
+
|
|
5541
|
+
// Parses array and generator comprehensions.
|
|
5542
|
+
|
|
5543
|
+
function parseComprehension(node, isGenerator) {
|
|
5544
|
+
node.blocks = [];
|
|
5545
|
+
while (tokType === _for) {
|
|
5546
|
+
var block = startNode();
|
|
5547
|
+
next();
|
|
5548
|
+
expect(_parenL);
|
|
5549
|
+
block.left = toAssignable(parseExprAtom());
|
|
5550
|
+
checkLVal(block.left, true);
|
|
5551
|
+
if (tokType !== _name || tokVal !== "of") unexpected();
|
|
5552
|
+
next();
|
|
5553
|
+
// `of` property is here for compatibility with Esprima's AST
|
|
5554
|
+
// which also supports deprecated [for (... in ...) expr]
|
|
5555
|
+
block.of = true;
|
|
5556
|
+
block.right = parseExpression();
|
|
5557
|
+
expect(_parenR);
|
|
5558
|
+
node.blocks.push(finishNode(block, "ComprehensionBlock"));
|
|
5559
|
+
}
|
|
5560
|
+
node.filter = eat(_if) ? parseParenExpression() : null;
|
|
5561
|
+
node.body = parseExpression();
|
|
5562
|
+
expect(isGenerator ? _parenR : _bracketR);
|
|
5563
|
+
node.generator = isGenerator;
|
|
5564
|
+
return finishNode(node, "ComprehensionExpression");
|
|
5565
|
+
}
|
|
2829
5566
|
|
|
2830
|
-
}
|
|
5567
|
+
});
|
|
5568
|
+
|
|
5569
|
+
},{}],15:[function(require,module,exports){
|
|
2831
5570
|
// alter.js
|
|
2832
5571
|
// MIT licensed, see LICENSE file
|
|
2833
5572
|
// Copyright (c) 2013 Olov Lassus <olov.lassus@gmail.com>
|
|
@@ -2874,7 +5613,7 @@ if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
|
|
|
2874
5613
|
module.exports = alter;
|
|
2875
5614
|
}
|
|
2876
5615
|
|
|
2877
|
-
},{"assert":1,"stable":
|
|
5616
|
+
},{"assert":1,"stable":31}],16:[function(require,module,exports){
|
|
2878
5617
|
/*
|
|
2879
5618
|
Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>
|
|
2880
5619
|
Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>
|
|
@@ -6632,7 +9371,7 @@ parseStatement: true, parseSourceElement: true */
|
|
|
6632
9371
|
}));
|
|
6633
9372
|
/* vim: set sw=4 ts=4 et tw=80 : */
|
|
6634
9373
|
|
|
6635
|
-
},{}],
|
|
9374
|
+
},{}],17:[function(require,module,exports){
|
|
6636
9375
|
// ordered-esprima-props.js
|
|
6637
9376
|
// MIT licensed, see LICENSE file
|
|
6638
9377
|
// Copyright (c) 2014 Olov Lassus <olov.lassus@gmail.com>
|
|
@@ -6711,7 +9450,7 @@ module.exports = (function() {
|
|
|
6711
9450
|
};
|
|
6712
9451
|
})();
|
|
6713
9452
|
|
|
6714
|
-
},{}],
|
|
9453
|
+
},{}],18:[function(require,module,exports){
|
|
6715
9454
|
// ordered-ast-traverse.js
|
|
6716
9455
|
// MIT licensed, see LICENSE file
|
|
6717
9456
|
// Copyright (c) 2014 Olov Lassus <olov.lassus@gmail.com>
|
|
@@ -6772,7 +9511,7 @@ if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
|
|
|
6772
9511
|
module.exports = traverse;
|
|
6773
9512
|
}
|
|
6774
9513
|
|
|
6775
|
-
},{"ordered-esprima-props":
|
|
9514
|
+
},{"ordered-esprima-props":17}],19:[function(require,module,exports){
|
|
6776
9515
|
// simple-fmt.js
|
|
6777
9516
|
// MIT licensed, see LICENSE file
|
|
6778
9517
|
// Copyright (c) 2013 Olov Lassus <olov.lassus@gmail.com>
|
|
@@ -6807,7 +9546,7 @@ if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
|
|
|
6807
9546
|
module.exports = fmt;
|
|
6808
9547
|
}
|
|
6809
9548
|
|
|
6810
|
-
},{}],
|
|
9549
|
+
},{}],20:[function(require,module,exports){
|
|
6811
9550
|
// simple-is.js
|
|
6812
9551
|
// MIT licensed, see LICENSE file
|
|
6813
9552
|
// Copyright (c) 2013 Olov Lassus <olov.lassus@gmail.com>
|
|
@@ -6865,7 +9604,7 @@ if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
|
|
|
6865
9604
|
module.exports = is;
|
|
6866
9605
|
}
|
|
6867
9606
|
|
|
6868
|
-
},{}],
|
|
9607
|
+
},{}],21:[function(require,module,exports){
|
|
6869
9608
|
/*
|
|
6870
9609
|
* Copyright 2009-2011 Mozilla Foundation and contributors
|
|
6871
9610
|
* Licensed under the New BSD license. See LICENSE.txt or:
|
|
@@ -6875,7 +9614,7 @@ exports.SourceMapGenerator = require('./source-map/source-map-generator').Source
|
|
|
6875
9614
|
exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer;
|
|
6876
9615
|
exports.SourceNode = require('./source-map/source-node').SourceNode;
|
|
6877
9616
|
|
|
6878
|
-
},{"./source-map/source-map-consumer":
|
|
9617
|
+
},{"./source-map/source-map-consumer":26,"./source-map/source-map-generator":27,"./source-map/source-node":28}],22:[function(require,module,exports){
|
|
6879
9618
|
/* -*- Mode: js; js-indent-level: 2; -*- */
|
|
6880
9619
|
/*
|
|
6881
9620
|
* Copyright 2011 Mozilla Foundation and contributors
|
|
@@ -6974,7 +9713,7 @@ define(function (require, exports, module) {
|
|
|
6974
9713
|
|
|
6975
9714
|
});
|
|
6976
9715
|
|
|
6977
|
-
},{"./util":
|
|
9716
|
+
},{"./util":29,"amdefine":30}],23:[function(require,module,exports){
|
|
6978
9717
|
/* -*- Mode: js; js-indent-level: 2; -*- */
|
|
6979
9718
|
/*
|
|
6980
9719
|
* Copyright 2011 Mozilla Foundation and contributors
|
|
@@ -7092,9 +9831,9 @@ define(function (require, exports, module) {
|
|
|
7092
9831
|
|
|
7093
9832
|
/**
|
|
7094
9833
|
* Decodes the next base 64 VLQ value from the given string and returns the
|
|
7095
|
-
* value and the rest of the string.
|
|
9834
|
+
* value and the rest of the string via the out parameter.
|
|
7096
9835
|
*/
|
|
7097
|
-
exports.decode = function base64VLQ_decode(aStr) {
|
|
9836
|
+
exports.decode = function base64VLQ_decode(aStr, aOutParam) {
|
|
7098
9837
|
var i = 0;
|
|
7099
9838
|
var strLen = aStr.length;
|
|
7100
9839
|
var result = 0;
|
|
@@ -7112,15 +9851,13 @@ define(function (require, exports, module) {
|
|
|
7112
9851
|
shift += VLQ_BASE_SHIFT;
|
|
7113
9852
|
} while (continuation);
|
|
7114
9853
|
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
rest: aStr.slice(i)
|
|
7118
|
-
};
|
|
9854
|
+
aOutParam.value = fromVLQSigned(result);
|
|
9855
|
+
aOutParam.rest = aStr.slice(i);
|
|
7119
9856
|
};
|
|
7120
9857
|
|
|
7121
9858
|
});
|
|
7122
9859
|
|
|
7123
|
-
},{"./base64":
|
|
9860
|
+
},{"./base64":24,"amdefine":30}],24:[function(require,module,exports){
|
|
7124
9861
|
/* -*- Mode: js; js-indent-level: 2; -*- */
|
|
7125
9862
|
/*
|
|
7126
9863
|
* Copyright 2011 Mozilla Foundation and contributors
|
|
@@ -7164,7 +9901,7 @@ define(function (require, exports, module) {
|
|
|
7164
9901
|
|
|
7165
9902
|
});
|
|
7166
9903
|
|
|
7167
|
-
},{"amdefine":
|
|
9904
|
+
},{"amdefine":30}],25:[function(require,module,exports){
|
|
7168
9905
|
/* -*- Mode: js; js-indent-level: 2; -*- */
|
|
7169
9906
|
/*
|
|
7170
9907
|
* Copyright 2011 Mozilla Foundation and contributors
|
|
@@ -7247,7 +9984,7 @@ define(function (require, exports, module) {
|
|
|
7247
9984
|
|
|
7248
9985
|
});
|
|
7249
9986
|
|
|
7250
|
-
},{"amdefine":
|
|
9987
|
+
},{"amdefine":30}],26:[function(require,module,exports){
|
|
7251
9988
|
/* -*- Mode: js; js-indent-level: 2; -*- */
|
|
7252
9989
|
/*
|
|
7253
9990
|
* Copyright 2011 Mozilla Foundation and contributors
|
|
@@ -7427,6 +10164,12 @@ define(function (require, exports, module) {
|
|
|
7427
10164
|
}
|
|
7428
10165
|
});
|
|
7429
10166
|
|
|
10167
|
+
SourceMapConsumer.prototype._nextCharIsMappingSeparator =
|
|
10168
|
+
function SourceMapConsumer_nextCharIsMappingSeparator(aStr) {
|
|
10169
|
+
var c = aStr.charAt(0);
|
|
10170
|
+
return c === ";" || c === ",";
|
|
10171
|
+
};
|
|
10172
|
+
|
|
7430
10173
|
/**
|
|
7431
10174
|
* Parse the mappings in a string in to a data structure which we can easily
|
|
7432
10175
|
* query (the ordered arrays in the `this.__generatedMappings` and
|
|
@@ -7440,10 +10183,9 @@ define(function (require, exports, module) {
|
|
|
7440
10183
|
var previousOriginalColumn = 0;
|
|
7441
10184
|
var previousSource = 0;
|
|
7442
10185
|
var previousName = 0;
|
|
7443
|
-
var mappingSeparator = /^[,;]/;
|
|
7444
10186
|
var str = aStr;
|
|
10187
|
+
var temp = {};
|
|
7445
10188
|
var mapping;
|
|
7446
|
-
var temp;
|
|
7447
10189
|
|
|
7448
10190
|
while (str.length > 0) {
|
|
7449
10191
|
if (str.charAt(0) === ';') {
|
|
@@ -7459,41 +10201,41 @@ define(function (require, exports, module) {
|
|
|
7459
10201
|
mapping.generatedLine = generatedLine;
|
|
7460
10202
|
|
|
7461
10203
|
// Generated column.
|
|
7462
|
-
|
|
10204
|
+
base64VLQ.decode(str, temp);
|
|
7463
10205
|
mapping.generatedColumn = previousGeneratedColumn + temp.value;
|
|
7464
10206
|
previousGeneratedColumn = mapping.generatedColumn;
|
|
7465
10207
|
str = temp.rest;
|
|
7466
10208
|
|
|
7467
|
-
if (str.length > 0 && !
|
|
10209
|
+
if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) {
|
|
7468
10210
|
// Original source.
|
|
7469
|
-
|
|
10211
|
+
base64VLQ.decode(str, temp);
|
|
7470
10212
|
mapping.source = this._sources.at(previousSource + temp.value);
|
|
7471
10213
|
previousSource += temp.value;
|
|
7472
10214
|
str = temp.rest;
|
|
7473
|
-
if (str.length === 0 ||
|
|
10215
|
+
if (str.length === 0 || this._nextCharIsMappingSeparator(str)) {
|
|
7474
10216
|
throw new Error('Found a source, but no line and column');
|
|
7475
10217
|
}
|
|
7476
10218
|
|
|
7477
10219
|
// Original line.
|
|
7478
|
-
|
|
10220
|
+
base64VLQ.decode(str, temp);
|
|
7479
10221
|
mapping.originalLine = previousOriginalLine + temp.value;
|
|
7480
10222
|
previousOriginalLine = mapping.originalLine;
|
|
7481
10223
|
// Lines are stored 0-based
|
|
7482
10224
|
mapping.originalLine += 1;
|
|
7483
10225
|
str = temp.rest;
|
|
7484
|
-
if (str.length === 0 ||
|
|
10226
|
+
if (str.length === 0 || this._nextCharIsMappingSeparator(str)) {
|
|
7485
10227
|
throw new Error('Found a source and line, but no column');
|
|
7486
10228
|
}
|
|
7487
10229
|
|
|
7488
10230
|
// Original column.
|
|
7489
|
-
|
|
10231
|
+
base64VLQ.decode(str, temp);
|
|
7490
10232
|
mapping.originalColumn = previousOriginalColumn + temp.value;
|
|
7491
10233
|
previousOriginalColumn = mapping.originalColumn;
|
|
7492
10234
|
str = temp.rest;
|
|
7493
10235
|
|
|
7494
|
-
if (str.length > 0 && !
|
|
10236
|
+
if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) {
|
|
7495
10237
|
// Original name.
|
|
7496
|
-
|
|
10238
|
+
base64VLQ.decode(str, temp);
|
|
7497
10239
|
mapping.name = this._names.at(previousName + temp.value);
|
|
7498
10240
|
previousName += temp.value;
|
|
7499
10241
|
str = temp.rest;
|
|
@@ -7727,7 +10469,7 @@ define(function (require, exports, module) {
|
|
|
7727
10469
|
|
|
7728
10470
|
});
|
|
7729
10471
|
|
|
7730
|
-
},{"./array-set":
|
|
10472
|
+
},{"./array-set":22,"./base64-vlq":23,"./binary-search":25,"./util":29,"amdefine":30}],27:[function(require,module,exports){
|
|
7731
10473
|
/* -*- Mode: js; js-indent-level: 2; -*- */
|
|
7732
10474
|
/*
|
|
7733
10475
|
* Copyright 2011 Mozilla Foundation and contributors
|
|
@@ -7934,9 +10676,7 @@ define(function (require, exports, module) {
|
|
|
7934
10676
|
}
|
|
7935
10677
|
mapping.originalLine = original.line;
|
|
7936
10678
|
mapping.originalColumn = original.column;
|
|
7937
|
-
if (original.name != null
|
|
7938
|
-
// Only use the identifier name if it's an identifier
|
|
7939
|
-
// in both SourceMaps
|
|
10679
|
+
if (original.name != null) {
|
|
7940
10680
|
mapping.name = original.name;
|
|
7941
10681
|
}
|
|
7942
10682
|
}
|
|
@@ -8132,7 +10872,7 @@ define(function (require, exports, module) {
|
|
|
8132
10872
|
|
|
8133
10873
|
});
|
|
8134
10874
|
|
|
8135
|
-
},{"./array-set":
|
|
10875
|
+
},{"./array-set":22,"./base64-vlq":23,"./util":29,"amdefine":30}],28:[function(require,module,exports){
|
|
8136
10876
|
/* -*- Mode: js; js-indent-level: 2; -*- */
|
|
8137
10877
|
/*
|
|
8138
10878
|
* Copyright 2011 Mozilla Foundation and contributors
|
|
@@ -8542,7 +11282,7 @@ define(function (require, exports, module) {
|
|
|
8542
11282
|
|
|
8543
11283
|
});
|
|
8544
11284
|
|
|
8545
|
-
},{"./source-map-generator":
|
|
11285
|
+
},{"./source-map-generator":27,"./util":29,"amdefine":30}],29:[function(require,module,exports){
|
|
8546
11286
|
/* -*- Mode: js; js-indent-level: 2; -*- */
|
|
8547
11287
|
/*
|
|
8548
11288
|
* Copyright 2011 Mozilla Foundation and contributors
|
|
@@ -8863,7 +11603,7 @@ define(function (require, exports, module) {
|
|
|
8863
11603
|
|
|
8864
11604
|
});
|
|
8865
11605
|
|
|
8866
|
-
},{"amdefine":
|
|
11606
|
+
},{"amdefine":30}],30:[function(require,module,exports){
|
|
8867
11607
|
(function (process,__filename){
|
|
8868
11608
|
/** vim: et:ts=4:sw=4:sts=4
|
|
8869
11609
|
* @license amdefine 0.1.0 Copyright (c) 2011, The Dojo Foundation All Rights Reserved.
|
|
@@ -9166,7 +11906,7 @@ function amdefine(module, requireFn) {
|
|
|
9166
11906
|
module.exports = amdefine;
|
|
9167
11907
|
|
|
9168
11908
|
}).call(this,require('_process'),"/node_modules/ng-annotate/node_modules/source-map/node_modules/amdefine/amdefine.js")
|
|
9169
|
-
},{"_process":5,"path":4}],
|
|
11909
|
+
},{"_process":5,"path":4}],31:[function(require,module,exports){
|
|
9170
11910
|
//! stable.js 0.1.5, https://github.com/Two-Screen/stable
|
|
9171
11911
|
//! © 2014 Angry Bytes and contributors. MIT licensed.
|
|
9172
11912
|
|
|
@@ -9279,7 +12019,7 @@ else {
|
|
|
9279
12019
|
|
|
9280
12020
|
})();
|
|
9281
12021
|
|
|
9282
|
-
},{}],
|
|
12022
|
+
},{}],32:[function(require,module,exports){
|
|
9283
12023
|
// stringmap.js
|
|
9284
12024
|
// MIT licensed, see LICENSE file
|
|
9285
12025
|
// Copyright (c) 2013 Olov Lassus <olov.lassus@gmail.com>
|
|
@@ -9525,7 +12265,7 @@ if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
|
|
|
9525
12265
|
module.exports = StringMap;
|
|
9526
12266
|
}
|
|
9527
12267
|
|
|
9528
|
-
},{}],
|
|
12268
|
+
},{}],33:[function(require,module,exports){
|
|
9529
12269
|
// stringset.js
|
|
9530
12270
|
// MIT licensed, see LICENSE file
|
|
9531
12271
|
// Copyright (c) 2013 Olov Lassus <olov.lassus@gmail.com>
|