Merge acorn 0.12.1 and acorn-babel (formerly "embed acorn" in the original git history).
This commit is contained in:
commit
16e8224ce6
@ -1,7 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1 +0,0 @@
|
||||
* text eol=lf
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,4 +0,0 @@
|
||||
/node_modules
|
||||
/.tern-port
|
||||
/acorn_csp.js
|
||||
/local
|
||||
@ -1,3 +0,0 @@
|
||||
/.tern-port
|
||||
/test
|
||||
/local
|
||||
@ -1 +0,0 @@
|
||||
{}
|
||||
@ -1,2 +0,0 @@
|
||||
language: node_js
|
||||
node_js: '0.10'
|
||||
313
README.md
313
README.md
@ -1,313 +1,4 @@
|
||||
# Acorn
|
||||
|
||||
[](https://travis-ci.org/marijnh/acorn)
|
||||
[](https://www.npmjs.org/package/acorn)
|
||||
[Author funding status: ](https://marijnhaverbeke.nl/fund/)
|
||||
|
||||
A tiny, fast JavaScript parser, written completely in JavaScript.
|
||||
|
||||
## Installation
|
||||
|
||||
The easiest way to install acorn is with [`npm`][npm].
|
||||
|
||||
[npm]: http://npmjs.org
|
||||
|
||||
```sh
|
||||
npm install acorn
|
||||
```
|
||||
|
||||
Alternately, download the source.
|
||||
|
||||
```sh
|
||||
git clone https://github.com/marijnh/acorn.git
|
||||
```
|
||||
|
||||
## Components
|
||||
|
||||
When run in a CommonJS (node.js) or AMD environment, exported values
|
||||
appear in the interfaces exposed by the individual files, as usual.
|
||||
When loaded in the browser (Acorn works in any JS-enabled browser more
|
||||
recent than IE5) without any kind of module management, a single
|
||||
global object `acorn` will be defined, and all the exported properties
|
||||
will be added to that.
|
||||
|
||||
### acorn.js
|
||||
|
||||
This file contains the actual parser (and is what you get when you
|
||||
`require("acorn")` in node.js).
|
||||
|
||||
**parse**`(input, options)` is used to parse a JavaScript program.
|
||||
The `input` parameter is a string, `options` can be undefined or an
|
||||
object setting some of the options listed below. The return value will
|
||||
be an abstract syntax tree object as specified by the
|
||||
[Mozilla Parser API][mozapi].
|
||||
|
||||
When encountering a syntax error, the parser will raise a
|
||||
`SyntaxError` object with a meaningful message. The error object will
|
||||
have a `pos` property that indicates the character offset at which the
|
||||
error occurred, and a `loc` object that contains a `{line, column}`
|
||||
object referring to that same position.
|
||||
|
||||
[mozapi]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
|
||||
|
||||
- **ecmaVersion**: Indicates the ECMAScript version to parse. Must be
|
||||
either 3, 5, or 6. This influences support for strict mode, the set
|
||||
of reserved words, and support for new syntax features. Default is 5.
|
||||
|
||||
- **strictSemicolons**: If `true`, prevents the parser from doing
|
||||
automatic semicolon insertion, and statements that do not end with
|
||||
a semicolon will generate an error. Defaults to `false`.
|
||||
|
||||
- **allowTrailingCommas**: If `false`, the parser will not allow
|
||||
trailing commas in array and object literals. Default is `true`.
|
||||
|
||||
- **forbidReserved**: If `true`, using a reserved word will generate
|
||||
an error. Defaults to `false`. When given the value `"everywhere"`,
|
||||
reserved words and keywords can also not be used as property names
|
||||
(as in Internet Explorer's old parser).
|
||||
|
||||
- **allowReturnOutsideFunction**: By default, a return statement at
|
||||
the top level raises an error. Set this to `true` to accept such
|
||||
code.
|
||||
|
||||
- **allowImportExportEverywhere**: By default, `import` and `export`
|
||||
declarations can only appear at a program's top level. Setting this
|
||||
option to `true` allows them anywhere where a statement is allowed.
|
||||
|
||||
- **allowHashBang**: When this is enabled (off by default), if the
|
||||
code starts with the characters `#!` (as in a shellscript), the
|
||||
first line will be treated as a comment.
|
||||
|
||||
- **locations**: When `true`, each node has a `loc` object attached
|
||||
with `start` and `end` subobjects, each of which contains the
|
||||
one-based line and zero-based column numbers in `{line, column}`
|
||||
form. Default is `false`.
|
||||
|
||||
- **onToken**: If a function is passed for this option, each found
|
||||
token will be passed in same format as `tokenize()` returns.
|
||||
|
||||
If array is passed, each found token is pushed to it.
|
||||
|
||||
Note that you are not allowed to call the parser from the
|
||||
callback—that will corrupt its internal state.
|
||||
|
||||
- **onComment**: If a function is passed for this option, whenever a
|
||||
comment is encountered the function will be called with the
|
||||
following parameters:
|
||||
|
||||
- `block`: `true` if the comment is a block comment, false if it
|
||||
is a line comment.
|
||||
- `text`: The content of the comment.
|
||||
- `start`: Character offset of the start of the comment.
|
||||
- `end`: Character offset of the end of the comment.
|
||||
|
||||
When the `locations` options is on, the `{line, column}` locations
|
||||
of the comment’s start and end are passed as two additional
|
||||
parameters.
|
||||
|
||||
If array is passed for this option, each found comment is pushed
|
||||
to it as object in Esprima format:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"type": "Line" | "Block",
|
||||
"value": "comment text",
|
||||
"range": ...,
|
||||
"loc": ...
|
||||
}
|
||||
```
|
||||
|
||||
Note that you are not allowed to call the parser from the
|
||||
callback—that will corrupt its internal state.
|
||||
|
||||
- **ranges**: Nodes have their start and end characters offsets
|
||||
recorded in `start` and `end` properties (directly on the node,
|
||||
rather than the `loc` object, which holds line/column data. To also
|
||||
add a [semi-standardized][range] "range" property holding a
|
||||
`[start, end]` array with the same numbers, set the `ranges` option
|
||||
to `true`.
|
||||
|
||||
- **program**: It is possible to parse multiple files into a single
|
||||
AST by passing the tree produced by parsing the first file as the
|
||||
`program` option in subsequent parses. This will add the toplevel
|
||||
forms of the parsed file to the "Program" (top) node of an existing
|
||||
parse tree.
|
||||
|
||||
- **sourceFile**: When the `locations` option is `true`, you can pass
|
||||
this option to add a `source` attribute in every node’s `loc`
|
||||
object. Note that the contents of this option are not examined or
|
||||
processed in any way; you are free to use whatever format you
|
||||
choose.
|
||||
|
||||
- **directSourceFile**: Like `sourceFile`, but a `sourceFile` property
|
||||
will be added directly to the nodes, rather than the `loc` object.
|
||||
|
||||
- **preserveParens**: If this option is `true`, parenthesized expressions
|
||||
are represented by (non-standard) `ParenthesizedExpression` nodes
|
||||
that have a single `expression` property containing the expression
|
||||
inside parentheses.
|
||||
|
||||
[range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
|
||||
|
||||
**parseExpressionAt**`(input, offset, options)` will parse a single
|
||||
expression in a string, and return its AST. It will not complain if
|
||||
there is more of the string left after the expression.
|
||||
|
||||
**getLineInfo**`(input, offset)` can be used to get a `{line,
|
||||
column}` object for a given program string and character offset.
|
||||
|
||||
**tokenize**`(input, options)` exports a primitive interface to
|
||||
Acorn's tokenizer. The function takes an input string and options
|
||||
similar to `parse` (though only some options are meaningful here), and
|
||||
returns a function that can be called repeatedly to read a single
|
||||
token, and returns a `{start, end, type, value}` object (with added
|
||||
`loc` property when the `locations` option is enabled and `range`
|
||||
property when the `ranges` option is enabled).
|
||||
|
||||
In ES6 environment, returned result can be used as any other protocol-compliant iterable:
|
||||
|
||||
```javascript
|
||||
for (let token of acorn.tokenize(str)) {
|
||||
// iterate over the tokens
|
||||
}
|
||||
|
||||
// transform code to array of tokens:
|
||||
var tokens = [...acorn.tokenize(str)];
|
||||
```
|
||||
|
||||
**tokTypes** holds an object mapping names to the token type objects
|
||||
that end up in the `type` properties of tokens.
|
||||
|
||||
#### Note on using with [Escodegen][escodegen]
|
||||
|
||||
Escodegen supports generating comments from AST, attached in
|
||||
Esprima-specific format. In order to simulate same format in
|
||||
Acorn, consider following example:
|
||||
|
||||
```javascript
|
||||
var comments = [], tokens = [];
|
||||
|
||||
var ast = acorn.parse('var x = 42; // answer', {
|
||||
// collect ranges for each node
|
||||
ranges: true,
|
||||
// collect comments in Esprima's format
|
||||
onComment: comments,
|
||||
// collect token ranges
|
||||
onToken: tokens
|
||||
});
|
||||
|
||||
// attach comments using collected information
|
||||
escodegen.attachComments(ast, comments, tokens);
|
||||
|
||||
// generate code
|
||||
console.log(escodegen.generate(ast, {comment: true}));
|
||||
// > 'var x = 42; // answer'
|
||||
```
|
||||
|
||||
[escodegen]: https://github.com/Constellation/escodegen
|
||||
|
||||
#### Using Acorn in an environment with a Content Security Policy
|
||||
|
||||
Some contexts, such as Chrome Web Apps, disallow run-time code evaluation.
|
||||
Acorn uses `new Function` to generate fast functions that test whether
|
||||
a word is in a given set, and will trigger a security error when used
|
||||
in a context with such a
|
||||
[Content Security Policy](http://www.html5rocks.com/en/tutorials/security/content-security-policy/#eval-too)
|
||||
(see [#90](https://github.com/marijnh/acorn/issues/90) and
|
||||
[#123](https://github.com/marijnh/acorn/issues/123)).
|
||||
|
||||
The `bin/without_eval` script can be used to generate a version of
|
||||
`acorn.js` that has the generated code inlined, and can thus run
|
||||
without evaluating anything. In versions of this library downloaded
|
||||
from NPM, this script will be available as `acorn_csp.js`.
|
||||
|
||||
### acorn_loose.js ###
|
||||
|
||||
This file implements an error-tolerant parser. It exposes a single
|
||||
function.
|
||||
|
||||
**parse_dammit**`(input, options)` takes the same arguments and
|
||||
returns the same syntax tree as the `parse` function in `acorn.js`,
|
||||
but never raises an error, and will do its best to parse syntactically
|
||||
invalid code in as meaningful a way as it can. It'll insert identifier
|
||||
nodes with name `"✖"` as placeholders in places where it can't make
|
||||
sense of the input. Depends on `acorn.js`, because it uses the same
|
||||
tokenizer.
|
||||
|
||||
### util/walk.js ###
|
||||
|
||||
Implements an abstract syntax tree walker. Will store its interface in
|
||||
`acorn.walk` when used without a module system.
|
||||
|
||||
**simple**`(node, visitors, base, state)` does a 'simple' walk over
|
||||
a tree. `node` should be the AST node to walk, and `visitors` an
|
||||
object with properties whose names correspond to node types in the
|
||||
[Mozilla Parser API][mozapi]. The properties should contain functions
|
||||
that will be called with the node object and, if applicable the state
|
||||
at that point. The last two arguments are optional. `base` is a walker
|
||||
algorithm, and `state` is a start state. The default walker will
|
||||
simply visit all statements and expressions and not produce a
|
||||
meaningful state. (An example of a use of state it to track scope at
|
||||
each point in the tree.)
|
||||
|
||||
**ancestor**`(node, visitors, base, state)` does a 'simple' walk over
|
||||
a tree, building up an array of ancestor nodes (including the current node)
|
||||
and passing the array to callbacks in the `state` parameter.
|
||||
|
||||
**recursive**`(node, state, functions, base)` does a 'recursive'
|
||||
walk, where the walker functions are responsible for continuing the
|
||||
walk on the child nodes of their target node. `state` is the start
|
||||
state, and `functions` should contain an object that maps node types
|
||||
to walker functions. Such functions are called with `(node, state, c)`
|
||||
arguments, and can cause the walk to continue on a sub-node by calling
|
||||
the `c` argument on it with `(node, state)` arguments. The optional
|
||||
`base` argument provides the fallback walker functions for node types
|
||||
that aren't handled in the `functions` object. If not given, the
|
||||
default walkers will be used.
|
||||
|
||||
**make**`(functions, base)` builds a new walker object by using the
|
||||
walker functions in `functions` and filling in the missing ones by
|
||||
taking defaults from `base`.
|
||||
|
||||
**findNodeAt**`(node, start, end, test, base, state)` tries to
|
||||
locate a node in a tree at the given start and/or end offsets, which
|
||||
satisfies the predicate `test`. `start` end `end` can be either `null`
|
||||
(as wildcard) or a number. `test` may be a string (indicating a node
|
||||
type) or a function that takes `(nodeType, node)` arguments and
|
||||
returns a boolean indicating whether this node is interesting. `base`
|
||||
and `state` are optional, and can be used to specify a custom walker.
|
||||
Nodes are tested from inner to outer, so if two nodes match the
|
||||
boundaries, the inner one will be preferred.
|
||||
|
||||
**findNodeAround**`(node, pos, test, base, state)` is a lot like
|
||||
`findNodeAt`, but will match any node that exists 'around' (spanning)
|
||||
the given position.
|
||||
|
||||
**findNodeAfter**`(node, pos, test, base, state)` is similar to
|
||||
`findNodeAround`, but will match all nodes *after* the given position
|
||||
(testing outer nodes before inner nodes).
|
||||
|
||||
## Command line interface
|
||||
|
||||
The `bin/acorn` utility can be used to parse a file from the command
|
||||
line. It accepts as arguments its input file and the following
|
||||
options:
|
||||
|
||||
- `--ecma3|--ecma5|--ecma6`: Sets the ECMAScript version to parse. Default is
|
||||
version 5.
|
||||
|
||||
- `--strictSemicolons`: Prevents the parser from doing automatic
|
||||
semicolon insertion. Statements that do not end in semicolons will
|
||||
generate an error.
|
||||
|
||||
- `--locations`: Attaches a "loc" object to each node with "start" and
|
||||
"end" subobjects, each of which contains the one-based line and
|
||||
zero-based column numbers in `{line, column}` form.
|
||||
|
||||
- `--compact`: No whitespace is used in the AST output.
|
||||
|
||||
- `--silent`: Do not output the AST, just return the exit status.
|
||||
|
||||
- `--help`: Print the usage information and quit.
|
||||
|
||||
The utility spits out the syntax tree as JSON data.
|
||||
Embedded version with Babel-specific modifications of the excellent
|
||||
[acorn](https://github.com/marijnh/acorn) parser.
|
||||
|
||||
285
acorn.js
285
acorn.js
@ -51,17 +51,20 @@
|
||||
// mode, the set of reserved words, support for getters and
|
||||
// setters and other features.
|
||||
ecmaVersion: 5,
|
||||
// Turn on `strictSemicolons` to prevent the parser from doing
|
||||
// automatic semicolon insertion.
|
||||
strictSemicolons: false,
|
||||
// When `allowTrailingCommas` is false, the parser will not allow
|
||||
// trailing commas in array and object literals.
|
||||
allowTrailingCommas: true,
|
||||
// By default, reserved words are not enforced. Enable
|
||||
// `forbidReserved` to enforce them. When this option has the
|
||||
// value "everywhere", reserved words and keywords can also not be
|
||||
// `onInsertedSemicolon` can be a callback that will be called
|
||||
// when a semicolon is automatically inserted. It will be passed
|
||||
// th position of the comma as an offset, and if `locations` is
|
||||
// enabled, it is given the location as a `{line, column}` object
|
||||
// as second argument.
|
||||
onInsertedSemicolon: null,
|
||||
// `onTrailingComma` is similar to `onInsertedSemicolon`, but for
|
||||
// trailing commas.
|
||||
onTrailingComma: null,
|
||||
// By default, reserved words are not enforced. Disable
|
||||
// `allowReserved` to enforce them. When this option has the
|
||||
// value "never", reserved words and keywords can also not be
|
||||
// used as property names.
|
||||
forbidReserved: false,
|
||||
allowReserved: true,
|
||||
// When enabled, a return at the top level is not considered an
|
||||
// error.
|
||||
allowReturnOutsideFunction: false,
|
||||
@ -117,7 +120,10 @@
|
||||
// When enabled, parenthesized expressions are represented by
|
||||
// (non-standard) ParenthesizedExpression nodes
|
||||
preserveParens: false,
|
||||
plugins: {}
|
||||
plugins: {},
|
||||
// Babel-specific options
|
||||
transformers: {},
|
||||
strictMode: false
|
||||
};
|
||||
|
||||
exports.plugins = {};
|
||||
@ -235,6 +241,7 @@
|
||||
this.label = label;
|
||||
this.keyword = conf.keyword;
|
||||
this.beforeExpr = !!conf.beforeExpr;
|
||||
this.rightAssociative = !!conf.rightAssociative;
|
||||
this.isLoop = !!conf.isLoop;
|
||||
this.isAssign = !!conf.isAssign;
|
||||
this.prefix = !!conf.prefix;
|
||||
@ -302,7 +309,8 @@
|
||||
plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true}),
|
||||
modulo: binop("%", 10),
|
||||
star: binop("*", 10),
|
||||
slash: binop("/", 10)
|
||||
slash: binop("/", 10),
|
||||
exponent: new TokenType("**", {beforeExpr: true, binop: 11, rightAssociative: true})
|
||||
};
|
||||
|
||||
// Map keyword names to token types.
|
||||
@ -566,7 +574,7 @@
|
||||
this.startLoc = this.endLoc = null;
|
||||
|
||||
// Position information for the previous token
|
||||
this.lastTokEndLoc = null;
|
||||
this.lastTokEndLoc = this.lastTokStartLoc = null;
|
||||
this.lastTokStart = this.lastTokEnd = this.pos;
|
||||
|
||||
// The context stack is used to superficially track syntactic
|
||||
@ -611,6 +619,7 @@
|
||||
this.lastTokEnd = this.end;
|
||||
this.lastTokStart = this.start;
|
||||
this.lastTokEndLoc = this.endLoc;
|
||||
this.lastTokStartLoc = this.startLoc;
|
||||
this.nextToken();
|
||||
};
|
||||
|
||||
@ -898,9 +907,22 @@
|
||||
};
|
||||
|
||||
pp.readToken_mult_modulo = function(code) { // '%*'
|
||||
var type = code === 42 ? tt.star : tt.modulo;
|
||||
var width = 1;
|
||||
var next = this.input.charCodeAt(this.pos + 1);
|
||||
if (next === 61) return this.finishOp(tt.assign, 2);
|
||||
return this.finishOp(code === 42 ? tt.star : tt.modulo, 1);
|
||||
|
||||
if (this.options.transformers["es7.exponentiationOperator"] && next === 42) { // '*'
|
||||
width++;
|
||||
next = this.input.charCodeAt(this.pos + 2);
|
||||
type = tt.exponent;
|
||||
}
|
||||
|
||||
if (next === 61) {
|
||||
width++;
|
||||
type = tt.assign;
|
||||
}
|
||||
|
||||
return this.finishOp(type, width);
|
||||
};
|
||||
|
||||
pp.readToken_pipe_amp = function(code) { // '|&'
|
||||
@ -1078,7 +1100,7 @@
|
||||
// ASCII symbol to avoid throwing on regular expressions that
|
||||
// are only valid in combination with the `/u` flag.
|
||||
tmp = tmp
|
||||
.replace(/\\u\{([0-9a-fA-F]{5,6})\}/g, "x")
|
||||
.replace(/\\u\{([0-9a-fA-F]+)\}/g, "x")
|
||||
.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "x");
|
||||
}
|
||||
}
|
||||
@ -1453,15 +1475,33 @@
|
||||
// Test whether a semicolon can be inserted at the current position.
|
||||
|
||||
pp.canInsertSemicolon = function() {
|
||||
return !this.options.strictSemicolons &&
|
||||
(this.type === tt.eof || this.type === tt.braceR || newline.test(this.input.slice(this.lastTokEnd, this.start)));
|
||||
return this.type === tt.eof ||
|
||||
this.type === tt.braceR ||
|
||||
newline.test(this.input.slice(this.lastTokEnd, this.start));
|
||||
};
|
||||
|
||||
pp.insertSemicolon = function() {
|
||||
if (this.canInsertSemicolon()) {
|
||||
if (this.options.onInsertedSemicolon)
|
||||
this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc)
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Consume a semicolon, or, failing that, see if we are allowed to
|
||||
// pretend that there is a semicolon at this position.
|
||||
|
||||
pp.semicolon = function() {
|
||||
if (!this.eat(tt.semi) && !this.canInsertSemicolon()) this.unexpected();
|
||||
if (!this.eat(tt.semi) && !this.insertSemicolon()) this.unexpected();
|
||||
};
|
||||
|
||||
pp.afterTrailingComma = function(tokType) {
|
||||
if (this.type == tokType) {
|
||||
if (this.options.onTrailingComma)
|
||||
this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc);
|
||||
this.next();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Expect a token of a given type. If found, consume it, otherwise,
|
||||
@ -1583,7 +1623,7 @@
|
||||
case tt.bracketL:
|
||||
var node = this.startNode();
|
||||
this.next();
|
||||
node.elements = this.parseBindingList(tt.bracketR, true);
|
||||
node.elements = this.parseBindingList(tt.bracketR, true, true);
|
||||
return this.finishNode(node, "ArrayPattern");
|
||||
|
||||
case tt.braceL:
|
||||
@ -1594,20 +1634,30 @@
|
||||
}
|
||||
};
|
||||
|
||||
pp.parseBindingList = function(close, allowEmpty) {
|
||||
pp.parseBindingList = function(close, allowEmpty, allowTrailingComma) {
|
||||
var elts = [], first = true;
|
||||
while (!this.eat(close)) {
|
||||
first ? first = false : this.expect(tt.comma);
|
||||
if (this.type === tt.ellipsis) {
|
||||
elts.push(this.parseRest());
|
||||
if (first) first = false;
|
||||
else this.expect(tt.comma);
|
||||
if (allowEmpty && this.type === tt.comma) {
|
||||
elts.push(null);
|
||||
} else if (allowTrailingComma && this.afterTrailingComma(close)) {
|
||||
break;
|
||||
} else if (this.type === tt.ellipsis) {
|
||||
elts.push(this.parseAssignableListItemTypes(this.parseRest()));
|
||||
this.expect(close);
|
||||
break;
|
||||
} else {
|
||||
elts.push(this.parseAssignableListItemTypes(this.parseMaybeDefault()));
|
||||
}
|
||||
elts.push(allowEmpty && this.type === tt.comma ? null : this.parseMaybeDefault());
|
||||
}
|
||||
return elts;
|
||||
};
|
||||
|
||||
pp.parseAssignableListItemTypes = function(param) {
|
||||
return param;
|
||||
};
|
||||
|
||||
// Parses assignment pattern around given atom if possible.
|
||||
|
||||
pp.parseMaybeDefault = function(startPos, left) {
|
||||
@ -1695,8 +1745,11 @@
|
||||
break;
|
||||
|
||||
case "ObjectPattern":
|
||||
for (var i = 0; i < expr.properties.length; i++)
|
||||
this.checkLVal(expr.properties[i].value, isBinding);
|
||||
for (var i = 0; i < expr.properties.length; i++) {
|
||||
var prop = expr.properties[i];
|
||||
if (prop.type === "Property") prop = prop.value;
|
||||
this.checkLVal(prop, isBinding);
|
||||
}
|
||||
break;
|
||||
|
||||
case "ArrayPattern":
|
||||
@ -1710,6 +1763,7 @@
|
||||
this.checkLVal(expr.left);
|
||||
break;
|
||||
|
||||
case "SpreadProperty":
|
||||
case "RestElement":
|
||||
this.checkLVal(expr.argument);
|
||||
break;
|
||||
@ -1773,7 +1827,7 @@
|
||||
case tt._throw: return this.parseThrowStatement(node);
|
||||
case tt._try: return this.parseTryStatement(node);
|
||||
case tt._let: case tt._const: if (!declaration) this.unexpected(); // NOTE: falls through to _var
|
||||
case tt._var: return this.parseVarStatement(node, starttype.keyword);
|
||||
case tt._var: return this.parseVarStatement(node, starttype);
|
||||
case tt._while: return this.parseWhileStatement(node);
|
||||
case tt._with: return this.parseWithStatement(node);
|
||||
case tt.braceL: return this.parseBlock(); // no point creating a function for this
|
||||
@ -1800,7 +1854,7 @@
|
||||
pp.parseBreakContinueStatement = function(node, keyword) {
|
||||
var isBreak = keyword == "break";
|
||||
this.next();
|
||||
if (this.eat(tt.semi) || this.canInsertSemicolon()) node.label = null;
|
||||
if (this.eat(tt.semi) || this.insertSemicolon()) node.label = null;
|
||||
else if (this.type !== tt.name) this.unexpected();
|
||||
else {
|
||||
node.label = this.parseIdent();
|
||||
@ -1853,13 +1907,13 @@
|
||||
this.labels.push(loopLabel);
|
||||
this.expect(tt.parenL);
|
||||
if (this.type === tt.semi) return this.parseFor(node, null);
|
||||
if (this.type === tt._var || this.type === tt._let) {
|
||||
var init = this.startNode(), varKind = this.type.keyword, isLet = this.type === tt._let;
|
||||
if (this.type === tt._var || this.type === tt._let || this.type === tt._const) {
|
||||
var init = this.startNode(), varKind = this.type;
|
||||
this.next();
|
||||
this.parseVar(init, true, varKind);
|
||||
this.finishNode(init, "VariableDeclaration");
|
||||
if ((this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init.declarations.length === 1 &&
|
||||
!(isLet && init.declarations[0].init))
|
||||
!(varKind !== tt._var && init.declarations[0].init))
|
||||
return this.parseForIn(node, init);
|
||||
return this.parseFor(node, init);
|
||||
}
|
||||
@ -1897,7 +1951,7 @@
|
||||
// optional arguments, we eagerly look for a semicolon or the
|
||||
// possibility to insert one.
|
||||
|
||||
if (this.eat(tt.semi) || this.canInsertSemicolon()) node.argument = null;
|
||||
if (this.eat(tt.semi) || this.insertSemicolon()) node.argument = null;
|
||||
else { node.argument = this.parseExpression(); this.semicolon(); }
|
||||
return this.finishNode(node, "ReturnStatement");
|
||||
};
|
||||
@ -2079,18 +2133,28 @@
|
||||
|
||||
pp.parseVar = function(node, noIn, kind) {
|
||||
node.declarations = [];
|
||||
node.kind = kind;
|
||||
node.kind = kind.keyword;
|
||||
for (;;) {
|
||||
var decl = this.startNode();
|
||||
decl.id = this.parseBindingAtom();
|
||||
this.checkLVal(decl.id, true);
|
||||
decl.init = this.eat(tt.eq) ? this.parseMaybeAssign(noIn) : (kind === tt._const.keyword ? this.unexpected() : null);
|
||||
this.parseVarHead(decl);
|
||||
if (this.eat(tt.eq)) {
|
||||
decl.init = this.parseMaybeAssign(noIn);
|
||||
} else if (kind === tt._const && !(this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) {
|
||||
this.unexpected();
|
||||
} else {
|
||||
decl.init = null;
|
||||
}
|
||||
node.declarations.push(this.finishNode(decl, "VariableDeclarator"));
|
||||
if (!this.eat(tt.comma)) break;
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
pp.parseVarHead = function (decl) {
|
||||
decl.id = this.parseBindingAtom();
|
||||
this.checkLVal(decl.id, true);
|
||||
};
|
||||
|
||||
// ### Expression parsing
|
||||
|
||||
// These nest, from the most general expression type at the top to
|
||||
@ -2121,7 +2185,9 @@
|
||||
// Parse an assignment expression. This includes applications of
|
||||
// operators like `+=`.
|
||||
|
||||
pp.parseMaybeAssign = function(noIn, refShorthandDefaultPos) {
|
||||
pp.parseMaybeAssign = function(noIn, refShorthandDefaultPos, afterLeftParse) {
|
||||
if (this.type == tt._yield && this.inGenerator) return this.parseYield();
|
||||
|
||||
var failOnShorthandAssign;
|
||||
if (!refShorthandDefaultPos) {
|
||||
refShorthandDefaultPos = {start: 0};
|
||||
@ -2131,6 +2197,7 @@
|
||||
}
|
||||
var start = this.currentPos();
|
||||
var left = this.parseMaybeConditional(noIn, refShorthandDefaultPos);
|
||||
if (afterLeftParse) left = afterLeftParse.call(this, left, start);
|
||||
if (this.type.isAssign) {
|
||||
var node = this.startNodeAt(start);
|
||||
node.operator = this.value;
|
||||
@ -2188,7 +2255,7 @@
|
||||
var op = this.type;
|
||||
this.next();
|
||||
var start = this.currentPos();
|
||||
node.right = this.parseExprOp(this.parseMaybeUnary(), start, prec, noIn);
|
||||
node.right = this.parseExprOp(this.parseMaybeUnary(), start, op.rightAssociative ? (prec - 1) : prec, noIn);
|
||||
this.finishNode(node, (op === tt.logicalOR || op === tt.logicalAND) ? "LogicalExpression" : "BinaryExpression");
|
||||
return this.parseExprOp(node, leftStart, minPrec, noIn);
|
||||
}
|
||||
@ -2276,7 +2343,7 @@
|
||||
return this.finishNode(node, "ThisExpression");
|
||||
|
||||
case tt._yield:
|
||||
if (this.inGenerator) return this.parseYield();
|
||||
if (this.inGenerator) unexpected();
|
||||
|
||||
case tt.name:
|
||||
var start = this.currentPos();
|
||||
@ -2309,7 +2376,7 @@
|
||||
var node = this.startNode();
|
||||
this.next();
|
||||
// check whether this is array comprehension or regular array
|
||||
if (this.options.ecmaVersion >= 7 && this.type === tt._for) {
|
||||
if (this.options.transformers["es7.comprehensions"] && this.type === tt._for) {
|
||||
return this.parseComprehension(node, false);
|
||||
}
|
||||
node.elements = this.parseExprList(tt.bracketR, true, true, refShorthandDefaultPos);
|
||||
@ -2350,7 +2417,7 @@
|
||||
if (this.options.ecmaVersion >= 6) {
|
||||
this.next();
|
||||
|
||||
if (this.options.ecmaVersion >= 7 && this.type === tt._for) {
|
||||
if (this.options.transformers["es7.comprehensions"] && this.type === tt._for) {
|
||||
return this.parseComprehension(this.startNodeAt(start), true);
|
||||
}
|
||||
|
||||
@ -2359,14 +2426,15 @@
|
||||
while (this.type !== tt.parenR) {
|
||||
first ? first = false : this.expect(tt.comma);
|
||||
if (this.type === tt.ellipsis) {
|
||||
var spreadNodeStart = this.currentPos();
|
||||
spreadStart = this.start;
|
||||
exprList.push(this.parseRest());
|
||||
exprList.push(this.parseParenItem(this.parseRest(), spreadNodeStart));
|
||||
break;
|
||||
} else {
|
||||
if (this.type === tt.parenL && !innerParenStart) {
|
||||
innerParenStart = this.start;
|
||||
}
|
||||
exprList.push(this.parseMaybeAssign(false, refShorthandDefaultPos));
|
||||
exprList.push(this.parseMaybeAssign(false, refShorthandDefaultPos, this.parseParenItem));
|
||||
}
|
||||
}
|
||||
var innerEnd = this.currentPos();
|
||||
@ -2401,6 +2469,10 @@
|
||||
}
|
||||
};
|
||||
|
||||
pp.parseParenItem = function (node, start) {
|
||||
return node;
|
||||
};
|
||||
|
||||
// New's precedence is slightly tricky. It must allow its argument
|
||||
// to be a `[]` or dot subscript expression, but not a call — at
|
||||
// least, not without wrapping it in parentheses. Thus, it uses the
|
||||
@ -2453,10 +2525,16 @@
|
||||
while (!this.eat(tt.braceR)) {
|
||||
if (!first) {
|
||||
this.expect(tt.comma);
|
||||
if (this.options.allowTrailingCommas && this.eat(tt.braceR)) break;
|
||||
if (this.afterTrailingComma(tt.braceR)) break;
|
||||
} else first = false;
|
||||
|
||||
var prop = this.startNode(), isGenerator, start;
|
||||
if (this.options.transformers["es7.objectRestSpread"] && this.type === tt.ellipsis) {
|
||||
prop = this.parseSpread();
|
||||
prop.type = "SpreadProperty";
|
||||
node.properties.push(prop);
|
||||
continue;
|
||||
}
|
||||
if (this.options.ecmaVersion >= 6) {
|
||||
prop.method = false;
|
||||
prop.shorthand = false;
|
||||
@ -2538,19 +2616,23 @@
|
||||
if (isStatement || this.type === tt.name) {
|
||||
node.id = this.parseIdent();
|
||||
}
|
||||
this.expect(tt.parenL);
|
||||
node.params = this.parseBindingList(tt.parenR, false);
|
||||
this.parseFunctionParams(node);
|
||||
this.parseFunctionBody(node, allowExpressionBody);
|
||||
return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression");
|
||||
};
|
||||
|
||||
pp.parseFunctionParams = function(node) {
|
||||
this.expect(tt.parenL);
|
||||
node.params = this.parseBindingList(tt.parenR, false, false);
|
||||
};
|
||||
|
||||
// Parse object or class method.
|
||||
|
||||
pp.parseMethod = function(isGenerator) {
|
||||
var node = this.startNode();
|
||||
this.initFunction(node);
|
||||
this.expect(tt.parenL);
|
||||
node.params = this.parseBindingList(tt.parenR, false);
|
||||
node.params = this.parseBindingList(tt.parenR, false, false);
|
||||
var allowExpressionBody;
|
||||
if (this.options.ecmaVersion >= 6) {
|
||||
node.generator = isGenerator;
|
||||
@ -2606,8 +2688,8 @@
|
||||
|
||||
pp.parseClass = function(node, isStatement) {
|
||||
this.next();
|
||||
node.id = this.type === tt.name ? this.parseIdent() : isStatement ? this.unexpected() : null;
|
||||
node.superClass = this.eat(tt._extends) ? this.parseExprSubscripts() : null;
|
||||
this.parseClassId(node, isStatement);
|
||||
this.parseClassSuper(node);
|
||||
var classBody = this.startNode();
|
||||
classBody.body = [];
|
||||
this.expect(tt.braceL);
|
||||
@ -2640,6 +2722,14 @@
|
||||
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression");
|
||||
};
|
||||
|
||||
pp.parseClassId = function (node, isStatement) {
|
||||
node.id = this.type === tt.name ? this.parseIdent() : isStatement ? this.unexpected() : null;
|
||||
};
|
||||
|
||||
pp.parseClassSuper = function (node) {
|
||||
node.superClass = this.eat(tt._extends) ? this.parseExprSubscripts() : null;
|
||||
};
|
||||
|
||||
// Parses a comma-separated list of expressions, and returns them as
|
||||
// an array. `close` is the token type that ends the list, and
|
||||
// `allowEmpty` can be turned on to allow subsequent commas with
|
||||
@ -2651,7 +2741,7 @@
|
||||
while (!this.eat(close)) {
|
||||
if (!first) {
|
||||
this.expect(tt.comma);
|
||||
if (allowTrailingComma && this.options.allowTrailingCommas && this.eat(close)) break;
|
||||
if (allowTrailingComma && this.afterTrailingComma(close)) break;
|
||||
} else first = false;
|
||||
|
||||
if (allowEmpty && this.type === tt.comma) {
|
||||
@ -2672,10 +2762,10 @@
|
||||
|
||||
pp.parseIdent = function(liberal) {
|
||||
var node = this.startNode();
|
||||
if (liberal && this.options.forbidReserved == "everywhere") liberal = false;
|
||||
if (liberal && this.options.allowReserved == "never") liberal = false;
|
||||
if (this.type === tt.name) {
|
||||
if (!liberal &&
|
||||
(this.options.forbidReserved &&
|
||||
(!this.options.allowReserved &&
|
||||
(this.options.ecmaVersion === 3 ? isReservedWord3 : isReservedWord5)(this.value) ||
|
||||
this.strict && isStrictReservedWord(this.value)) &&
|
||||
this.input.slice(this.start, this.end).indexOf("\\") == -1)
|
||||
@ -2694,15 +2784,13 @@
|
||||
|
||||
pp.parseExport = function(node) {
|
||||
this.next();
|
||||
// export var|const|let|function|class ...;
|
||||
if (this.type === tt._var || this.type === tt._const || this.type === tt._let || this.type === tt._function || this.type === tt._class) {
|
||||
node.declaration = this.parseStatement(true);
|
||||
node['default'] = false;
|
||||
node.specifiers = null;
|
||||
node.source = null;
|
||||
} else
|
||||
// export default ...;
|
||||
if (this.eat(tt._default)) {
|
||||
// export * from '...';
|
||||
if (this.eat(tt.star)) {
|
||||
this.expectContextual("from");
|
||||
node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected();
|
||||
return this.finishNode(node, "ExportAllDeclaration");
|
||||
}
|
||||
if (this.eat(tt._default)) { // export default ...;
|
||||
var expr = this.parseMaybeAssign();
|
||||
if (expr.id) {
|
||||
switch (expr.type) {
|
||||
@ -2711,51 +2799,43 @@
|
||||
}
|
||||
}
|
||||
node.declaration = expr;
|
||||
node['default'] = true;
|
||||
node.specifiers = null;
|
||||
node.source = null;
|
||||
this.semicolon();
|
||||
} else {
|
||||
// export * from '...';
|
||||
// export { x, y as z } [from '...'];
|
||||
var isBatch = this.type === tt.star;
|
||||
return this.finishNode(node, "ExportDefaultDeclaration");
|
||||
}
|
||||
// export var|const|let|function|class ...;
|
||||
if (this.type.keyword) {
|
||||
node.declaration = this.parseStatement(true);
|
||||
node.specifiers = [];
|
||||
node.source = null;
|
||||
} else { // export { x, y as z } [from '...'];
|
||||
node.declaration = null;
|
||||
node['default'] = false;
|
||||
node.specifiers = this.parseExportSpecifiers();
|
||||
if (this.eatContextual("from")) {
|
||||
node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected();
|
||||
} else {
|
||||
if (isBatch) this.unexpected();
|
||||
node.source = null;
|
||||
}
|
||||
this.semicolon();
|
||||
}
|
||||
return this.finishNode(node, "ExportDeclaration");
|
||||
return this.finishNode(node, "ExportNamedDeclaration");
|
||||
};
|
||||
|
||||
// Parses a comma-separated list of module exports.
|
||||
|
||||
pp.parseExportSpecifiers = function() {
|
||||
var nodes = [], first = true;
|
||||
if (this.type === tt.star) {
|
||||
// export * from '...'
|
||||
var node = this.startNode();
|
||||
this.next();
|
||||
nodes.push(this.finishNode(node, "ExportBatchSpecifier"));
|
||||
} else {
|
||||
// export { x, y as z } [from '...']
|
||||
this.expect(tt.braceL);
|
||||
while (!this.eat(tt.braceR)) {
|
||||
if (!first) {
|
||||
this.expect(tt.comma);
|
||||
if (this.options.allowTrailingCommas && this.eat(tt.braceR)) break;
|
||||
} else first = false;
|
||||
// export { x, y as z } [from '...']
|
||||
this.expect(tt.braceL);
|
||||
while (!this.eat(tt.braceR)) {
|
||||
if (!first) {
|
||||
this.expect(tt.comma);
|
||||
if (this.afterTrailingComma(tt.braceR)) break;
|
||||
} else first = false;
|
||||
|
||||
var node = this.startNode();
|
||||
node.id = this.parseIdent(this.type === tt._default);
|
||||
node.name = this.eatContextual("as") ? this.parseIdent(true) : null;
|
||||
nodes.push(this.finishNode(node, "ExportSpecifier"));
|
||||
}
|
||||
var node = this.startNode();
|
||||
node.local = this.parseIdent(this.type === tt._default);
|
||||
node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local;
|
||||
nodes.push(this.finishNode(node, "ExportSpecifier"));
|
||||
}
|
||||
return nodes;
|
||||
};
|
||||
@ -2785,34 +2865,31 @@
|
||||
if (this.type === tt.name) {
|
||||
// import defaultObj, { x, y as z } from '...'
|
||||
var node = this.startNode();
|
||||
node.id = this.parseIdent();
|
||||
this.checkLVal(node.id, true);
|
||||
node.name = null;
|
||||
node['default'] = true;
|
||||
nodes.push(this.finishNode(node, "ImportSpecifier"));
|
||||
node.local = this.parseIdent();
|
||||
this.checkLVal(node.local, true);
|
||||
nodes.push(this.finishNode(node, "ImportDefaultSpecifier"));
|
||||
if (!this.eat(tt.comma)) return nodes;
|
||||
}
|
||||
if (this.type === tt.star) {
|
||||
var node = this.startNode();
|
||||
this.next();
|
||||
this.expectContextual("as");
|
||||
node.name = this.parseIdent();
|
||||
this.checkLVal(node.name, true);
|
||||
nodes.push(this.finishNode(node, "ImportBatchSpecifier"));
|
||||
node.local = this.parseIdent();
|
||||
this.checkLVal(node.local, true);
|
||||
nodes.push(this.finishNode(node, "ImportNamespaceSpecifier"));
|
||||
return nodes;
|
||||
}
|
||||
this.expect(tt.braceL);
|
||||
while (!this.eat(tt.braceR)) {
|
||||
if (!first) {
|
||||
this.expect(tt.comma);
|
||||
if (this.options.allowTrailingCommas && this.eat(tt.braceR)) break;
|
||||
if (this.afterTrailingComma(tt.braceR)) break;
|
||||
} else first = false;
|
||||
|
||||
var node = this.startNode();
|
||||
node.id = this.parseIdent(true);
|
||||
node.name = this.eatContextual("as") ? this.parseIdent() : null;
|
||||
this.checkLVal(node.name || node.id, true);
|
||||
node['default'] = false;
|
||||
node.imported = this.parseIdent(true);
|
||||
node.local = this.eatContextual("as") ? this.parseIdent() : node.imported;
|
||||
this.checkLVal(node.local, true);
|
||||
nodes.push(this.finishNode(node, "ImportSpecifier"));
|
||||
}
|
||||
return nodes;
|
||||
@ -2823,7 +2900,7 @@
|
||||
pp.parseYield = function() {
|
||||
var node = this.startNode();
|
||||
this.next();
|
||||
if (this.eat(tt.semi) || this.canInsertSemicolon()) {
|
||||
if (this.type == tt.semi || this.canInsertSemicolon()) {
|
||||
node.delegate = false;
|
||||
node.argument = null;
|
||||
} else {
|
||||
|
||||
1150
acorn_loose.js
1150
acorn_loose.js
File diff suppressed because it is too large
Load Diff
54
bin/acorn
54
bin/acorn
@ -1,54 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var path = require("path");
|
||||
var fs = require("fs");
|
||||
var acorn = require("../acorn.js");
|
||||
|
||||
var infile, parsed, tokens, options = {}, silent = false, compact = false, tokenize = false;
|
||||
|
||||
function help(status) {
|
||||
var print = (status == 0) ? console.log : console.error;
|
||||
print("usage: " + path.basename(process.argv[1]) + " [--ecma3|--ecma5|--ecma6] [--strictSemicolons]");
|
||||
print(" [--tokenize] [--locations] [--compact] [--silent] [--help] [--] infile");
|
||||
process.exit(status);
|
||||
}
|
||||
|
||||
for (var i = 2; i < process.argv.length; ++i) {
|
||||
var arg = process.argv[i];
|
||||
if (arg[0] != "-" && !infile) infile = arg;
|
||||
else if (arg == "--" && !infile && i + 2 == process.argv.length) infile = process.argv[++i];
|
||||
else if (arg == "--ecma3") options.ecmaVersion = 3;
|
||||
else if (arg == "--ecma5") options.ecmaVersion = 5;
|
||||
else if (arg == "--ecma6") options.ecmaVersion = 6;
|
||||
else if (arg == "--ecma7") options.ecmaVersion = 7;
|
||||
else if (arg == "--strictSemicolons") options.strictSemicolons = true;
|
||||
else if (arg == "--locations") options.locations = true;
|
||||
else if (arg == "--silent") silent = true;
|
||||
else if (arg == "--compact") compact = true;
|
||||
else if (arg == "--help") help(0);
|
||||
else if (arg == "--tokenize") tokenize = true;
|
||||
else help(1);
|
||||
}
|
||||
|
||||
try {
|
||||
var code = fs.readFileSync(infile, "utf8");
|
||||
|
||||
if (!tokenize)
|
||||
parsed = acorn.parse(code, options);
|
||||
else {
|
||||
var get = acorn.tokenize(code, options);
|
||||
tokens = [];
|
||||
while (true) {
|
||||
var token = get();
|
||||
tokens.push(token);
|
||||
if (token.type.type == "eof")
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
console.log(e.message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!silent)
|
||||
console.log(JSON.stringify(tokenize ? tokens : parsed, null, compact ? null : 2));
|
||||
@ -1,6 +0,0 @@
|
||||
# Combine existing list of authors with everyone known in git, sort, add header.
|
||||
tail --lines=+3 AUTHORS > AUTHORS.tmp
|
||||
git log --format='%aN' | grep -v abraidwood >> AUTHORS.tmp
|
||||
echo -e "List of Acorn contributors. Updated before every release.\n" > AUTHORS
|
||||
sort -u AUTHORS.tmp >> AUTHORS
|
||||
rm -f AUTHORS.tmp
|
||||
@ -1,45 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var fs = require("fs");
|
||||
|
||||
var acornSrc = fs.readFileSync(require.resolve("../acorn"), "utf8");
|
||||
var acorn = require("../acorn"), walk = require("../util/walk");
|
||||
|
||||
var ast = acorn.parse(acornSrc);
|
||||
var touchups = [], uses = [];
|
||||
|
||||
walk.simple(ast, {
|
||||
FunctionDeclaration: function(node) {
|
||||
if (node.id.name == "makePredicate")
|
||||
touchups.push({text: "// Removed to create an eval-free library", from: node.start, to: node.end});
|
||||
},
|
||||
VariableDeclaration: function(node) {
|
||||
node.declarations.forEach(function(decl) {
|
||||
if (decl.init && decl.init.type == "CallExpression" &&
|
||||
decl.init.callee.name == "makePredicate")
|
||||
uses.push(decl);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var results = Object.create(null);
|
||||
var functions = new Function("predicates", acornSrc.replace(
|
||||
/\}\);\s*$/, uses.map(function(decl) {
|
||||
return "predicates[" + JSON.stringify(decl.id.name) + "] = " + decl.id.name + ";";
|
||||
}).join("") + "});"))(results);
|
||||
|
||||
uses.forEach(function(decl) {
|
||||
touchups.push({text: results[decl.id.name].toString(),
|
||||
from: decl.init.start, to: decl.init.end});
|
||||
});
|
||||
|
||||
var result = "", pos = 0;
|
||||
touchups.sort(function(a, b) { return a.from - b.from; });
|
||||
touchups.forEach(function(touchup) {
|
||||
result += acornSrc.slice(pos, touchup.from);
|
||||
result += touchup.text;
|
||||
pos = touchup.to;
|
||||
});
|
||||
result += acornSrc.slice(pos);
|
||||
|
||||
process.stdout.write(result);
|
||||
192
docco.css
192
docco.css
@ -1,192 +0,0 @@
|
||||
/*--------------------- Layout and Typography ----------------------------*/
|
||||
body {
|
||||
font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
color: #252519;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
a {
|
||||
color: #261a3b;
|
||||
}
|
||||
a:visited {
|
||||
color: #261a3b;
|
||||
}
|
||||
p {
|
||||
margin: 0 0 15px 0;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin: 0px 0 15px 0;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 40px;
|
||||
}
|
||||
hr {
|
||||
border: 0 none;
|
||||
border-top: 1px solid #e5e5ee;
|
||||
height: 1px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
#container {
|
||||
position: relative;
|
||||
}
|
||||
#background {
|
||||
position: fixed;
|
||||
top: 0; left: 525px; right: 0; bottom: 0;
|
||||
background: #f5f5ff;
|
||||
border-left: 1px solid #e5e5ee;
|
||||
z-index: -1;
|
||||
}
|
||||
#jump_to, #jump_page {
|
||||
background: white;
|
||||
-webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
|
||||
-webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;
|
||||
font: 10px Arial;
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
text-align: right;
|
||||
}
|
||||
#jump_to, #jump_wrapper {
|
||||
position: fixed;
|
||||
right: 0; top: 0;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
#jump_wrapper {
|
||||
padding: 0;
|
||||
display: none;
|
||||
}
|
||||
#jump_to:hover #jump_wrapper {
|
||||
display: block;
|
||||
}
|
||||
#jump_page {
|
||||
padding: 5px 0 3px;
|
||||
margin: 0 0 25px 25px;
|
||||
}
|
||||
#jump_page .source {
|
||||
display: block;
|
||||
padding: 5px 10px;
|
||||
text-decoration: none;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
#jump_page .source:hover {
|
||||
background: #f5f5ff;
|
||||
}
|
||||
#jump_page .source:first-child {
|
||||
}
|
||||
table td {
|
||||
border: 0;
|
||||
outline: 0;
|
||||
}
|
||||
td.docs, th.docs {
|
||||
max-width: 450px;
|
||||
min-width: 450px;
|
||||
min-height: 5px;
|
||||
padding: 10px 25px 1px 50px;
|
||||
overflow-x: hidden;
|
||||
vertical-align: top;
|
||||
text-align: left;
|
||||
}
|
||||
.docs pre {
|
||||
margin: 15px 0 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
.docs p tt, .docs p code {
|
||||
background: #f8f8ff;
|
||||
border: 1px solid #dedede;
|
||||
font-size: 12px;
|
||||
padding: 0 0.2em;
|
||||
}
|
||||
.pilwrap {
|
||||
position: relative;
|
||||
}
|
||||
.pilcrow {
|
||||
font: 12px Arial;
|
||||
text-decoration: none;
|
||||
color: #454545;
|
||||
position: absolute;
|
||||
top: 3px; left: -20px;
|
||||
padding: 1px 2px;
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
}
|
||||
td.docs:hover .pilcrow {
|
||||
opacity: 1;
|
||||
}
|
||||
td.code, th.code {
|
||||
padding: 14px 15px 16px 25px;
|
||||
width: 100%;
|
||||
vertical-align: top;
|
||||
background: #f5f5ff;
|
||||
border-left: 1px solid #e5e5ee;
|
||||
}
|
||||
pre, tt, code {
|
||||
font-size: 12px; line-height: 18px;
|
||||
font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------- Syntax Highlighting -----------------------------*/
|
||||
td.linenos { background-color: #f0f0f0; padding-right: 10px; }
|
||||
span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
|
||||
body .hll { background-color: #ffffcc }
|
||||
body .c { color: #408080; font-style: italic } /* Comment */
|
||||
body .err { border: 1px solid #FF0000 } /* Error */
|
||||
body .k { color: #954121 } /* Keyword */
|
||||
body .o { color: #666666 } /* Operator */
|
||||
body .cm { color: #408080; font-style: italic } /* Comment.Multiline */
|
||||
body .cp { color: #BC7A00 } /* Comment.Preproc */
|
||||
body .c1 { color: #408080; font-style: italic } /* Comment.Single */
|
||||
body .cs { color: #408080; font-style: italic } /* Comment.Special */
|
||||
body .gd { color: #A00000 } /* Generic.Deleted */
|
||||
body .ge { font-style: italic } /* Generic.Emph */
|
||||
body .gr { color: #FF0000 } /* Generic.Error */
|
||||
body .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
body .gi { color: #00A000 } /* Generic.Inserted */
|
||||
body .go { color: #808080 } /* Generic.Output */
|
||||
body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
||||
body .gs { font-weight: bold } /* Generic.Strong */
|
||||
body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
body .gt { color: #0040D0 } /* Generic.Traceback */
|
||||
body .kc { color: #954121 } /* Keyword.Constant */
|
||||
body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */
|
||||
body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */
|
||||
body .kp { color: #954121 } /* Keyword.Pseudo */
|
||||
body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */
|
||||
body .kt { color: #B00040 } /* Keyword.Type */
|
||||
body .m { color: #666666 } /* Literal.Number */
|
||||
body .s { color: #219161 } /* Literal.String */
|
||||
body .na { color: #7D9029 } /* Name.Attribute */
|
||||
body .nb { color: #954121 } /* Name.Builtin */
|
||||
body .nc { color: #0000FF; font-weight: bold } /* Name.Class */
|
||||
body .no { color: #880000 } /* Name.Constant */
|
||||
body .nd { color: #AA22FF } /* Name.Decorator */
|
||||
body .ni { color: #999999; font-weight: bold } /* Name.Entity */
|
||||
body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
|
||||
body .nf { color: #0000FF } /* Name.Function */
|
||||
body .nl { color: #A0A000 } /* Name.Label */
|
||||
body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
|
||||
body .nt { color: #954121; font-weight: bold } /* Name.Tag */
|
||||
body .nv { color: #19469D } /* Name.Variable */
|
||||
body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
|
||||
body .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
body .mf { color: #666666 } /* Literal.Number.Float */
|
||||
body .mh { color: #666666 } /* Literal.Number.Hex */
|
||||
body .mi { color: #666666 } /* Literal.Number.Integer */
|
||||
body .mo { color: #666666 } /* Literal.Number.Oct */
|
||||
body .sb { color: #219161 } /* Literal.String.Backtick */
|
||||
body .sc { color: #219161 } /* Literal.String.Char */
|
||||
body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */
|
||||
body .s2 { color: #219161 } /* Literal.String.Double */
|
||||
body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
|
||||
body .sh { color: #219161 } /* Literal.String.Heredoc */
|
||||
body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
|
||||
body .sx { color: #954121 } /* Literal.String.Other */
|
||||
body .sr { color: #BB6688 } /* Literal.String.Regex */
|
||||
body .s1 { color: #219161 } /* Literal.String.Single */
|
||||
body .ss { color: #19469D } /* Literal.String.Symbol */
|
||||
body .bp { color: #954121 } /* Name.Builtin.Pseudo */
|
||||
body .vc { color: #19469D } /* Name.Variable.Class */
|
||||
body .vg { color: #19469D } /* Name.Variable.Global */
|
||||
body .vi { color: #19469D } /* Name.Variable.Instance */
|
||||
body .il { color: #666666 } /* Literal.Number.Integer.Long */
|
||||
@ -5,6 +5,7 @@
|
||||
"main": "acorn.js",
|
||||
"version": "0.12.1",
|
||||
"engines": {"node": ">=0.4.0"},
|
||||
"browser": "acorn_csp.js",
|
||||
"maintainers": [{"name": "Marijn Haverbeke",
|
||||
"email": "marijnh@gmail.com",
|
||||
"web": "http://marijnhaverbeke.nl"}],
|
||||
|
||||
@ -17,43 +17,17 @@
|
||||
for (var i = 0; i < tests.length; ++i) {
|
||||
var test = tests[i];
|
||||
if (config.filter && !config.filter(test)) continue;
|
||||
var testOpts = test.options || {locations: true};
|
||||
var expected = {};
|
||||
if (expected.onComment = testOpts.onComment)
|
||||
testOpts.onComment = []
|
||||
if (expected.onToken = testOpts.onToken)
|
||||
testOpts.onToken = [];
|
||||
|
||||
try {
|
||||
var testOpts = test.options || {locations: true};
|
||||
var expected = {};
|
||||
if (expected.onComment = testOpts.onComment) {
|
||||
testOpts.onComment = []
|
||||
}
|
||||
if (expected.onToken = testOpts.onToken) {
|
||||
testOpts.onToken = [];
|
||||
}
|
||||
var ast = parse(test.code, testOpts);
|
||||
if (test.error) {
|
||||
if (config.loose) {
|
||||
callback("ok", test.code);
|
||||
} else {
|
||||
callback("fail", test.code, "Expected error message: " + test.error + "\nBut parsing succeeded.");
|
||||
}
|
||||
} else if (test.assert) {
|
||||
var error = test.assert(ast);
|
||||
if (error) callback("fail", test.code,
|
||||
"\n Assertion failed:\n " + error);
|
||||
else callback("ok", test.code);
|
||||
} else {
|
||||
var mis = misMatch(test.ast, ast);
|
||||
for (var name in expected) {
|
||||
if (mis) break;
|
||||
if (expected[name]) {
|
||||
mis = misMatch(expected[name], testOpts[name]);
|
||||
testOpts[name] = expected[name];
|
||||
}
|
||||
}
|
||||
if (mis) callback("fail", test.code, mis);
|
||||
else callback("ok", test.code);
|
||||
}
|
||||
} catch(e) {
|
||||
if (!(e instanceof SyntaxError)) {
|
||||
throw e;
|
||||
}
|
||||
if (!(e instanceof SyntaxError)) throw e;
|
||||
if (test.error) {
|
||||
if (e.message == test.error) callback("ok", test.code);
|
||||
else callback("fail", test.code,
|
||||
@ -61,6 +35,27 @@
|
||||
} else {
|
||||
callback("error", test.code, e.message || e.toString());
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (test.error) {
|
||||
if (config.loose) callback("ok", test.code);
|
||||
else callback("fail", test.code, "Expected error message: " + test.error + "\nBut parsing succeeded.");
|
||||
} else if (test.assert) {
|
||||
var error = test.assert(ast);
|
||||
if (error) callback("fail", test.code, "\n Assertion failed:\n " + error);
|
||||
else callback("ok", test.code);
|
||||
} else {
|
||||
var mis = misMatch(test.ast, ast);
|
||||
for (var name in expected) {
|
||||
if (mis) break;
|
||||
if (expected[name]) {
|
||||
mis = misMatch(expected[name], testOpts[name]);
|
||||
testOpts[name] = expected[name];
|
||||
}
|
||||
}
|
||||
if (mis) callback("fail", test.code, mis);
|
||||
else callback("ok", test.code);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -4453,7 +4453,7 @@ test("var {a:b} = {}", {
|
||||
test("export var document", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportNamedDeclaration",
|
||||
declaration: {
|
||||
type: "VariableDeclaration",
|
||||
declarations: [{
|
||||
@ -4478,8 +4478,7 @@ test("export var document", {
|
||||
end: {line: 1, column: 19}
|
||||
}
|
||||
},
|
||||
default: false,
|
||||
specifiers: null,
|
||||
specifiers: [],
|
||||
source: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 0},
|
||||
@ -4499,7 +4498,7 @@ test("export var document", {
|
||||
test("export var document = { }", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportNamedDeclaration",
|
||||
declaration: {
|
||||
type: "VariableDeclaration",
|
||||
declarations: [{
|
||||
@ -4531,8 +4530,7 @@ test("export var document = { }", {
|
||||
end: {line: 1, column: 25}
|
||||
}
|
||||
},
|
||||
default: false,
|
||||
specifiers: null,
|
||||
specifiers: [],
|
||||
source: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 0},
|
||||
@ -4552,7 +4550,7 @@ test("export var document = { }", {
|
||||
test("export let document", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportNamedDeclaration",
|
||||
declaration: {
|
||||
type: "VariableDeclaration",
|
||||
declarations: [{
|
||||
@ -4577,8 +4575,7 @@ test("export let document", {
|
||||
end: {line: 1, column: 19}
|
||||
}
|
||||
},
|
||||
default: false,
|
||||
specifiers: null,
|
||||
specifiers: [],
|
||||
source: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 0},
|
||||
@ -4598,7 +4595,7 @@ test("export let document", {
|
||||
test("export let document = { }", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportNamedDeclaration",
|
||||
declaration: {
|
||||
type: "VariableDeclaration",
|
||||
declarations: [{
|
||||
@ -4630,8 +4627,7 @@ test("export let document = { }", {
|
||||
end: {line: 1, column: 25}
|
||||
}
|
||||
},
|
||||
default: false,
|
||||
specifiers: null,
|
||||
specifiers: [],
|
||||
source: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 0},
|
||||
@ -4651,7 +4647,7 @@ test("export let document = { }", {
|
||||
test("export const document = { }", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportNamedDeclaration",
|
||||
declaration: {
|
||||
type: "VariableDeclaration",
|
||||
declarations: [{
|
||||
@ -4683,8 +4679,7 @@ test("export const document = { }", {
|
||||
end: {line: 1, column: 27}
|
||||
}
|
||||
},
|
||||
default: false,
|
||||
specifiers: null,
|
||||
specifiers: [],
|
||||
source: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 0},
|
||||
@ -4704,7 +4699,7 @@ test("export const document = { }", {
|
||||
test("export function parse() { }", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportNamedDeclaration",
|
||||
declaration: {
|
||||
type: "FunctionDeclaration",
|
||||
id: {
|
||||
@ -4731,8 +4726,7 @@ test("export function parse() { }", {
|
||||
end: {line: 1, column: 27}
|
||||
}
|
||||
},
|
||||
default: false,
|
||||
specifiers: null,
|
||||
specifiers: [],
|
||||
source: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 0},
|
||||
@ -4752,7 +4746,7 @@ test("export function parse() { }", {
|
||||
test("export class Class {}", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportNamedDeclaration",
|
||||
declaration: {
|
||||
type: "ClassDeclaration",
|
||||
id: {
|
||||
@ -4777,8 +4771,7 @@ test("export class Class {}", {
|
||||
end: {line: 1, column: 21}
|
||||
}
|
||||
},
|
||||
default: false,
|
||||
specifiers: null,
|
||||
specifiers: [],
|
||||
source: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 0},
|
||||
@ -4798,7 +4791,7 @@ test("export class Class {}", {
|
||||
test("export default 42", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportDefaultDeclaration",
|
||||
declaration: {
|
||||
type: "Literal",
|
||||
value: 42,
|
||||
@ -4808,9 +4801,6 @@ test("export default 42", {
|
||||
end: {line: 1, column: 17}
|
||||
}
|
||||
},
|
||||
default: true,
|
||||
specifiers: null,
|
||||
source: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 0},
|
||||
end: {line: 1, column: 17}
|
||||
@ -4830,7 +4820,7 @@ test("export default function () {}", {
|
||||
type: "Program",
|
||||
range: [0, 29],
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportDefaultDeclaration",
|
||||
range: [0, 29],
|
||||
declaration: {
|
||||
type: "FunctionExpression",
|
||||
@ -4844,10 +4834,7 @@ test("export default function () {}", {
|
||||
range: [27, 29],
|
||||
body: []
|
||||
}
|
||||
},
|
||||
default: true,
|
||||
specifiers: null,
|
||||
source: null
|
||||
}
|
||||
}]
|
||||
}, {ecmaVersion: 6, ranges: true});
|
||||
|
||||
@ -4855,7 +4842,7 @@ test("export default function f() {}", {
|
||||
type: "Program",
|
||||
range: [0, 30],
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportDefaultDeclaration",
|
||||
range: [0, 30],
|
||||
declaration: {
|
||||
type: "FunctionDeclaration",
|
||||
@ -4873,10 +4860,7 @@ test("export default function f() {}", {
|
||||
range: [28, 30],
|
||||
body: []
|
||||
}
|
||||
},
|
||||
default: true,
|
||||
specifiers: null,
|
||||
source: null
|
||||
}
|
||||
}]
|
||||
}, {ecmaVersion: 6, ranges: true});
|
||||
|
||||
@ -4884,7 +4868,7 @@ test("export default class {}", {
|
||||
type: "Program",
|
||||
range: [0, 23],
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportDefaultDeclaration",
|
||||
range: [0, 23],
|
||||
declaration: {
|
||||
type: "ClassExpression",
|
||||
@ -4896,10 +4880,7 @@ test("export default class {}", {
|
||||
range: [21, 23],
|
||||
body: []
|
||||
}
|
||||
},
|
||||
default: true,
|
||||
specifiers: null,
|
||||
source: null
|
||||
}
|
||||
}]
|
||||
}, {ecmaVersion: 6, ranges: true});
|
||||
|
||||
@ -4907,7 +4888,7 @@ test("export default class A {}", {
|
||||
type: "Program",
|
||||
range: [0, 25],
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportDefaultDeclaration",
|
||||
range: [0, 25],
|
||||
declaration: {
|
||||
type: "ClassDeclaration",
|
||||
@ -4923,10 +4904,7 @@ test("export default class A {}", {
|
||||
range: [23, 25],
|
||||
body: []
|
||||
}
|
||||
},
|
||||
default: true,
|
||||
specifiers: null,
|
||||
source: null
|
||||
}
|
||||
}]
|
||||
}, {ecmaVersion: 6, ranges: true});
|
||||
|
||||
@ -4935,15 +4913,7 @@ testFail("export *", "Unexpected token (1:8)", {ecmaVersion: 6});
|
||||
test("export * from \"crypto\"", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
declaration: null,
|
||||
specifiers: [{
|
||||
type: "ExportBatchSpecifier",
|
||||
loc: {
|
||||
start: {line: 1, column: 7},
|
||||
end: {line: 1, column: 8}
|
||||
}
|
||||
}],
|
||||
type: "ExportAllDeclaration",
|
||||
source: {
|
||||
type: "Literal",
|
||||
value: "crypto",
|
||||
@ -4971,11 +4941,19 @@ test("export * from \"crypto\"", {
|
||||
test("export { encrypt }", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportNamedDeclaration",
|
||||
declaration: null,
|
||||
specifiers: [{
|
||||
type: "ExportSpecifier",
|
||||
id: {
|
||||
exported: {
|
||||
type: "Identifier",
|
||||
name: "encrypt",
|
||||
loc: {
|
||||
start: {line: 1, column: 9},
|
||||
end: {line: 1, column: 16}
|
||||
}
|
||||
},
|
||||
local: {
|
||||
type: "Identifier",
|
||||
name: "encrypt",
|
||||
loc: {
|
||||
@ -4983,7 +4961,6 @@ test("export { encrypt }", {
|
||||
end: {line: 1, column: 16}
|
||||
}
|
||||
},
|
||||
name: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 9},
|
||||
end: {line: 1, column: 16}
|
||||
@ -5008,12 +4985,20 @@ test("export { encrypt }", {
|
||||
test("export { encrypt, decrypt }", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportNamedDeclaration",
|
||||
declaration: null,
|
||||
specifiers: [
|
||||
{
|
||||
type: "ExportSpecifier",
|
||||
id: {
|
||||
exported: {
|
||||
type: "Identifier",
|
||||
name: "encrypt",
|
||||
loc: {
|
||||
start: {line: 1, column: 9},
|
||||
end: {line: 1, column: 16}
|
||||
}
|
||||
},
|
||||
local: {
|
||||
type: "Identifier",
|
||||
name: "encrypt",
|
||||
loc: {
|
||||
@ -5021,7 +5006,6 @@ test("export { encrypt, decrypt }", {
|
||||
end: {line: 1, column: 16}
|
||||
}
|
||||
},
|
||||
name: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 9},
|
||||
end: {line: 1, column: 16}
|
||||
@ -5029,7 +5013,15 @@ test("export { encrypt, decrypt }", {
|
||||
},
|
||||
{
|
||||
type: "ExportSpecifier",
|
||||
id: {
|
||||
exported: {
|
||||
type: "Identifier",
|
||||
name: "decrypt",
|
||||
loc: {
|
||||
start: {line: 1, column: 18},
|
||||
end: {line: 1, column: 25}
|
||||
}
|
||||
},
|
||||
local: {
|
||||
type: "Identifier",
|
||||
name: "decrypt",
|
||||
loc: {
|
||||
@ -5037,7 +5029,6 @@ test("export { encrypt, decrypt }", {
|
||||
end: {line: 1, column: 25}
|
||||
}
|
||||
},
|
||||
name: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 18},
|
||||
end: {line: 1, column: 25}
|
||||
@ -5063,19 +5054,11 @@ test("export { encrypt, decrypt }", {
|
||||
test("export { encrypt as default }", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportNamedDeclaration",
|
||||
declaration: null,
|
||||
specifiers: [{
|
||||
type: "ExportSpecifier",
|
||||
id: {
|
||||
type: "Identifier",
|
||||
name: "encrypt",
|
||||
loc: {
|
||||
start: {line: 1, column: 9},
|
||||
end: {line: 1, column: 16}
|
||||
}
|
||||
},
|
||||
name: {
|
||||
exported: {
|
||||
type: "Identifier",
|
||||
name: "default",
|
||||
loc: {
|
||||
@ -5083,6 +5066,14 @@ test("export { encrypt as default }", {
|
||||
end: {line: 1, column: 27}
|
||||
}
|
||||
},
|
||||
local: {
|
||||
type: "Identifier",
|
||||
name: "encrypt",
|
||||
loc: {
|
||||
start: {line: 1, column: 9},
|
||||
end: {line: 1, column: 16}
|
||||
}
|
||||
},
|
||||
loc: {
|
||||
start: {line: 1, column: 9},
|
||||
end: {line: 1, column: 27}
|
||||
@ -5107,12 +5098,20 @@ test("export { encrypt as default }", {
|
||||
test("export { encrypt, decrypt as dec }", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportNamedDeclaration",
|
||||
declaration: null,
|
||||
specifiers: [
|
||||
{
|
||||
type: "ExportSpecifier",
|
||||
id: {
|
||||
exported: {
|
||||
type: "Identifier",
|
||||
name: "encrypt",
|
||||
loc: {
|
||||
start: {line: 1, column: 9},
|
||||
end: {line: 1, column: 16}
|
||||
}
|
||||
},
|
||||
local: {
|
||||
type: "Identifier",
|
||||
name: "encrypt",
|
||||
loc: {
|
||||
@ -5120,7 +5119,6 @@ test("export { encrypt, decrypt as dec }", {
|
||||
end: {line: 1, column: 16}
|
||||
}
|
||||
},
|
||||
name: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 9},
|
||||
end: {line: 1, column: 16}
|
||||
@ -5128,15 +5126,7 @@ test("export { encrypt, decrypt as dec }", {
|
||||
},
|
||||
{
|
||||
type: "ExportSpecifier",
|
||||
id: {
|
||||
type: "Identifier",
|
||||
name: "decrypt",
|
||||
loc: {
|
||||
start: {line: 1, column: 18},
|
||||
end: {line: 1, column: 25}
|
||||
}
|
||||
},
|
||||
name: {
|
||||
exported: {
|
||||
type: "Identifier",
|
||||
name: "dec",
|
||||
loc: {
|
||||
@ -5144,6 +5134,14 @@ test("export { encrypt, decrypt as dec }", {
|
||||
end: {line: 1, column: 32}
|
||||
}
|
||||
},
|
||||
local: {
|
||||
type: "Identifier",
|
||||
name: "decrypt",
|
||||
loc: {
|
||||
start: {line: 1, column: 18},
|
||||
end: {line: 1, column: 25}
|
||||
}
|
||||
},
|
||||
loc: {
|
||||
start: {line: 1, column: 18},
|
||||
end: {line: 1, column: 32}
|
||||
@ -5169,12 +5167,20 @@ test("export { encrypt, decrypt as dec }", {
|
||||
test("export { default } from \"other\"", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ExportDeclaration",
|
||||
type: "ExportNamedDeclaration",
|
||||
declaration: null,
|
||||
specifiers: [
|
||||
{
|
||||
type: "ExportSpecifier",
|
||||
id: {
|
||||
exported: {
|
||||
type: "Identifier",
|
||||
name: "default",
|
||||
loc: {
|
||||
start: {line: 1, column: 9},
|
||||
end: {line: 1, column: 16}
|
||||
}
|
||||
},
|
||||
local: {
|
||||
type: "Identifier",
|
||||
name: "default",
|
||||
loc: {
|
||||
@ -5182,7 +5188,6 @@ test("export { default } from \"other\"", {
|
||||
end: {line: 1, column: 16}
|
||||
}
|
||||
},
|
||||
name: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 9},
|
||||
end: {line: 1, column: 16}
|
||||
@ -5253,8 +5258,8 @@ test("import $ from \"jquery\"", {
|
||||
body: [{
|
||||
type: "ImportDeclaration",
|
||||
specifiers: [{
|
||||
type: "ImportSpecifier",
|
||||
id: {
|
||||
type: "ImportDefaultSpecifier",
|
||||
local: {
|
||||
type: "Identifier",
|
||||
name: "$",
|
||||
loc: {
|
||||
@ -5262,7 +5267,6 @@ test("import $ from \"jquery\"", {
|
||||
end: {line: 1, column: 8}
|
||||
}
|
||||
},
|
||||
name: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 7},
|
||||
end: {line: 1, column: 8}
|
||||
@ -5299,7 +5303,15 @@ test("import { encrypt, decrypt } from \"crypto\"", {
|
||||
specifiers: [
|
||||
{
|
||||
type: "ImportSpecifier",
|
||||
id: {
|
||||
imported: {
|
||||
type: "Identifier",
|
||||
name: "encrypt",
|
||||
loc: {
|
||||
start: {line: 1, column: 9},
|
||||
end: {line: 1, column: 16}
|
||||
}
|
||||
},
|
||||
local: {
|
||||
type: "Identifier",
|
||||
name: "encrypt",
|
||||
loc: {
|
||||
@ -5307,7 +5319,6 @@ test("import { encrypt, decrypt } from \"crypto\"", {
|
||||
end: {line: 1, column: 16}
|
||||
}
|
||||
},
|
||||
name: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 9},
|
||||
end: {line: 1, column: 16}
|
||||
@ -5315,7 +5326,15 @@ test("import { encrypt, decrypt } from \"crypto\"", {
|
||||
},
|
||||
{
|
||||
type: "ImportSpecifier",
|
||||
id: {
|
||||
imported: {
|
||||
type: "Identifier",
|
||||
name: "decrypt",
|
||||
loc: {
|
||||
start: {line: 1, column: 18},
|
||||
end: {line: 1, column: 25}
|
||||
}
|
||||
},
|
||||
local: {
|
||||
type: "Identifier",
|
||||
name: "decrypt",
|
||||
loc: {
|
||||
@ -5323,7 +5342,6 @@ test("import { encrypt, decrypt } from \"crypto\"", {
|
||||
end: {line: 1, column: 25}
|
||||
}
|
||||
},
|
||||
name: null,
|
||||
loc: {
|
||||
start: {line: 1, column: 18},
|
||||
end: {line: 1, column: 25}
|
||||
@ -5360,7 +5378,7 @@ test("import { encrypt as enc } from \"crypto\"", {
|
||||
type: "ImportDeclaration",
|
||||
specifiers: [{
|
||||
type: "ImportSpecifier",
|
||||
id: {
|
||||
imported: {
|
||||
type: "Identifier",
|
||||
name: "encrypt",
|
||||
loc: {
|
||||
@ -5368,7 +5386,7 @@ test("import { encrypt as enc } from \"crypto\"", {
|
||||
end: {line: 1, column: 16}
|
||||
}
|
||||
},
|
||||
name: {
|
||||
local: {
|
||||
type: "Identifier",
|
||||
name: "enc",
|
||||
loc: {
|
||||
@ -5419,21 +5437,19 @@ test("import crypto, { decrypt, encrypt as enc } from \"crypto\"", {
|
||||
},
|
||||
specifiers: [
|
||||
{
|
||||
type: "ImportSpecifier",
|
||||
type: "ImportDefaultSpecifier",
|
||||
loc: {
|
||||
start: {line: 1, column: 7},
|
||||
end: {line: 1, column: 13}
|
||||
},
|
||||
id: {
|
||||
local: {
|
||||
type: "Identifier",
|
||||
loc: {
|
||||
start: {line: 1, column: 7},
|
||||
end: {line: 1, column: 13}
|
||||
},
|
||||
name: "crypto"
|
||||
},
|
||||
name: null,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "ImportSpecifier",
|
||||
@ -5441,7 +5457,7 @@ test("import crypto, { decrypt, encrypt as enc } from \"crypto\"", {
|
||||
start: {line: 1, column: 17},
|
||||
end: {line: 1, column: 24}
|
||||
},
|
||||
id: {
|
||||
imported: {
|
||||
type: "Identifier",
|
||||
loc: {
|
||||
start: {line: 1, column: 17},
|
||||
@ -5449,8 +5465,14 @@ test("import crypto, { decrypt, encrypt as enc } from \"crypto\"", {
|
||||
},
|
||||
name: "decrypt"
|
||||
},
|
||||
name: null,
|
||||
default: false
|
||||
local: {
|
||||
type: "Identifier",
|
||||
loc: {
|
||||
start: {line: 1, column: 17},
|
||||
end: {line: 1, column: 24}
|
||||
},
|
||||
name: "decrypt"
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "ImportSpecifier",
|
||||
@ -5458,7 +5480,7 @@ test("import crypto, { decrypt, encrypt as enc } from \"crypto\"", {
|
||||
start: {line: 1, column: 26},
|
||||
end: {line: 1, column: 40}
|
||||
},
|
||||
id: {
|
||||
imported: {
|
||||
type: "Identifier",
|
||||
loc: {
|
||||
start: {line: 1, column: 26},
|
||||
@ -5466,15 +5488,14 @@ test("import crypto, { decrypt, encrypt as enc } from \"crypto\"", {
|
||||
},
|
||||
name: "encrypt"
|
||||
},
|
||||
name: {
|
||||
local: {
|
||||
type: "Identifier",
|
||||
loc: {
|
||||
start: {line: 1, column: 37},
|
||||
end: {line: 1, column: 40}
|
||||
},
|
||||
name: "enc"
|
||||
},
|
||||
default: false
|
||||
}
|
||||
}
|
||||
],
|
||||
source: {
|
||||
@ -5501,7 +5522,7 @@ test("import { null as nil } from \"bar\"", {
|
||||
type: "ImportDeclaration",
|
||||
specifiers: [{
|
||||
type: "ImportSpecifier",
|
||||
id: {
|
||||
imported: {
|
||||
type: "Identifier",
|
||||
name: "null",
|
||||
loc: {
|
||||
@ -5509,7 +5530,7 @@ test("import { null as nil } from \"bar\"", {
|
||||
end: {line: 1, column: 13}
|
||||
}
|
||||
},
|
||||
name: {
|
||||
local: {
|
||||
type: "Identifier",
|
||||
name: "nil",
|
||||
loc: {
|
||||
@ -5559,12 +5580,12 @@ test("import * as crypto from \"crypto\"", {
|
||||
end: {line: 1, column: 32}
|
||||
},
|
||||
specifiers: [{
|
||||
type: "ImportBatchSpecifier",
|
||||
type: "ImportNamespaceSpecifier",
|
||||
loc: {
|
||||
start: {line: 1, column: 7},
|
||||
end: {line: 1, column: 18}
|
||||
},
|
||||
name: {
|
||||
local: {
|
||||
type: "Identifier",
|
||||
loc: {
|
||||
start: {line: 1, column: 12},
|
||||
@ -13850,7 +13871,7 @@ testFail("function hello() {'use strict'; ({ i: 10, s(eval) { } }); }", "Definin
|
||||
|
||||
testFail("function a() { \"use strict\"; ({ b(t, t) { } }); }", "Argument name clash in strict mode (1:37)", {ecmaVersion: 6});
|
||||
|
||||
testFail("var super", "The keyword 'super' is reserved (1:4)", {ecmaVersion: 6, forbidReserved: true});
|
||||
testFail("var super", "The keyword 'super' is reserved (1:4)", {ecmaVersion: 6, allowReserved: false});
|
||||
|
||||
testFail("var default", "Unexpected token (1:4)", {ecmaVersion: 6});
|
||||
|
||||
@ -14346,17 +14367,15 @@ test("import foo, * as bar from 'baz';", {
|
||||
type: "ImportDeclaration",
|
||||
specifiers: [
|
||||
{
|
||||
type: "ImportSpecifier",
|
||||
id: {
|
||||
type: "ImportDefaultSpecifier",
|
||||
local: {
|
||||
type: "Identifier",
|
||||
name: "foo"
|
||||
},
|
||||
name: null,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "ImportBatchSpecifier",
|
||||
name: {
|
||||
type: "ImportNamespaceSpecifier",
|
||||
local: {
|
||||
type: "Identifier",
|
||||
name: "bar"
|
||||
}
|
||||
@ -14951,6 +14970,55 @@ test("class A { static() {} }", {
|
||||
locations: true
|
||||
});
|
||||
|
||||
// https://github.com/marijnh/acorn/issues/213
|
||||
|
||||
test("for (const x of list) process(x);", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ForOfStatement",
|
||||
left: {
|
||||
type: "VariableDeclaration",
|
||||
declarations: [{
|
||||
type: "VariableDeclarator",
|
||||
id: {
|
||||
type: "Identifier",
|
||||
name: "x",
|
||||
range: [11, 12]
|
||||
},
|
||||
init: null,
|
||||
range: [11, 12]
|
||||
}],
|
||||
kind: "const",
|
||||
range: [5, 12]
|
||||
},
|
||||
right: {
|
||||
type: "Identifier",
|
||||
name: "list",
|
||||
range: [16, 20]
|
||||
},
|
||||
body: {
|
||||
type: "ExpressionStatement",
|
||||
expression: {
|
||||
type: "CallExpression",
|
||||
callee: {
|
||||
type: "Identifier",
|
||||
name: "process",
|
||||
range: [22, 29]
|
||||
},
|
||||
arguments: [{
|
||||
type: "Identifier",
|
||||
name: "x",
|
||||
range: [30, 31]
|
||||
}],
|
||||
range: [22, 32]
|
||||
},
|
||||
range: [22, 33]
|
||||
},
|
||||
range: [0, 33]
|
||||
}],
|
||||
range: [0, 33]
|
||||
}, {ecmaVersion: 6, ranges: true});
|
||||
|
||||
test("class A { *static() {} }", {
|
||||
type: "Program",
|
||||
range: [0, 24],
|
||||
@ -15195,6 +15263,109 @@ test("var _\\u{104A6} = 10;", {
|
||||
]
|
||||
}, {ecmaVersion: 6});
|
||||
|
||||
test("let [x,] = [1]", {
|
||||
"start": 0,
|
||||
"body": [
|
||||
{
|
||||
"start": 0,
|
||||
"declarations": [
|
||||
{
|
||||
"start": 4,
|
||||
"id": {
|
||||
"start": 4,
|
||||
"elements": [
|
||||
{
|
||||
"start": 5,
|
||||
"name": "x",
|
||||
"type": "Identifier",
|
||||
"end": 6
|
||||
}
|
||||
],
|
||||
"type": "ArrayPattern",
|
||||
"end": 8
|
||||
},
|
||||
"init": {
|
||||
"start": 11,
|
||||
"elements": [
|
||||
{
|
||||
"start": 12,
|
||||
"value": 1,
|
||||
"raw": "1",
|
||||
"type": "Literal",
|
||||
"end": 13
|
||||
}
|
||||
],
|
||||
"type": "ArrayExpression",
|
||||
"end": 14
|
||||
},
|
||||
"type": "VariableDeclarator",
|
||||
"end": 14
|
||||
}
|
||||
],
|
||||
"kind": "let",
|
||||
"type": "VariableDeclaration",
|
||||
"end": 14
|
||||
}
|
||||
],
|
||||
"type": "Program",
|
||||
"end": 14
|
||||
}, {ecmaVersion: 6});
|
||||
|
||||
test("let {x} = y", {
|
||||
"start": 0,
|
||||
"body": [
|
||||
{
|
||||
"start": 0,
|
||||
"declarations": [
|
||||
{
|
||||
"start": 4,
|
||||
"id": {
|
||||
"start": 4,
|
||||
"properties": [
|
||||
{
|
||||
"start": 5,
|
||||
"method": false,
|
||||
"shorthand": true,
|
||||
"computed": false,
|
||||
"key": {
|
||||
"start": 5,
|
||||
"name": "x",
|
||||
"type": "Identifier",
|
||||
"end": 6
|
||||
},
|
||||
"kind": "init",
|
||||
"value": {
|
||||
"start": 5,
|
||||
"name": "x",
|
||||
"type": "Identifier",
|
||||
"end": 6
|
||||
},
|
||||
"type": "Property",
|
||||
"end": 6
|
||||
}
|
||||
],
|
||||
"type": "ObjectPattern",
|
||||
"end": 7
|
||||
},
|
||||
"init": {
|
||||
"start": 10,
|
||||
"name": "y",
|
||||
"type": "Identifier",
|
||||
"end": 11
|
||||
},
|
||||
"type": "VariableDeclarator",
|
||||
"end": 11
|
||||
}
|
||||
],
|
||||
"kind": "let",
|
||||
"type": "VariableDeclaration",
|
||||
"end": 11
|
||||
}
|
||||
],
|
||||
"type": "Program",
|
||||
"end": 11
|
||||
}, {ecmaVersion: 6})
|
||||
|
||||
testFail("var _𖫵 = 11;", "Unexpected character '𖫵' (1:5)", {ecmaVersion: 6});
|
||||
testFail("var _ = 12;", "Unexpected character '' (1:4)", {ecmaVersion: 6});
|
||||
testFail("var 𫠝_ = 10;", "Unexpected character '𫠝' (1:4)", {ecmaVersion: 5});
|
||||
|
||||
@ -28682,7 +28682,39 @@ test("const x = 14, y = 3, z = 1977", {
|
||||
|
||||
testFail("const a;", "Unexpected token (1:7)", {ecmaVersion: 6});
|
||||
|
||||
testFail("for(const x = 0;;);", "Unexpected token (1:4)", {ecmaVersion: 6});
|
||||
test("for(const x = 0;;);", {
|
||||
type: "Program",
|
||||
body: [{
|
||||
type: "ForStatement",
|
||||
init: {
|
||||
type: "VariableDeclaration",
|
||||
declarations: [{
|
||||
type: "VariableDeclarator",
|
||||
id: {
|
||||
type: "Identifier",
|
||||
name: "x",
|
||||
range: [10, 11]
|
||||
},
|
||||
init: {
|
||||
type: "Literal",
|
||||
value: 0,
|
||||
range: [14, 15]
|
||||
},
|
||||
range: [10, 15]
|
||||
}],
|
||||
kind: "const",
|
||||
range: [4, 15]
|
||||
},
|
||||
test: null,
|
||||
update: null,
|
||||
body: {
|
||||
type: "EmptyStatement",
|
||||
range: [18, 19]
|
||||
},
|
||||
range: [0, 19]
|
||||
}],
|
||||
range: [0, 19]
|
||||
}, {ecmaVersion: 6, ranges: true});
|
||||
|
||||
testFail("for(x of a);", "Unexpected token (1:6)");
|
||||
|
||||
@ -28914,3 +28946,22 @@ test("function f() {} / 1 /", {
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
var semicolons = []
|
||||
testAssert("var x\nreturn\n10", function() {
|
||||
var result = semicolons.join(" ");
|
||||
semicolons.length = 0;
|
||||
if (result != "5 12 15")
|
||||
return "Unexpected result for onInsertedSemicolon: " + result;
|
||||
}, {onInsertedSemicolon: function(pos) { semicolons.push(pos); },
|
||||
allowReturnOutsideFunction: true,
|
||||
loose: false})
|
||||
|
||||
var trailingCommas = []
|
||||
testAssert("[1,2,] + {foo: 1,}", function() {
|
||||
var result = trailingCommas.join(" ");
|
||||
trailingCommas.length = 0;
|
||||
if (result != "4 16")
|
||||
return "Unexpected result for onTrailingComma: " + result;
|
||||
}, {onTrailingComma: function(pos) { trailingCommas.push(pos); },
|
||||
loose: false})
|
||||
|
||||
359
util/walk.js
359
util/walk.js
@ -1,359 +0,0 @@
|
||||
// AST walker module for Mozilla Parser API compatible trees
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") return mod(exports); // CommonJS
|
||||
if (typeof define == "function" && define.amd) return define(["exports"], mod); // AMD
|
||||
mod((this.acorn || (this.acorn = {})).walk = {}); // Plain browser env
|
||||
})(function(exports) {
|
||||
"use strict";
|
||||
|
||||
// A simple walk is one where you simply specify callbacks to be
|
||||
// called on specific nodes. The last two arguments are optional. A
|
||||
// simple use would be
|
||||
//
|
||||
// walk.simple(myTree, {
|
||||
// Expression: function(node) { ... }
|
||||
// });
|
||||
//
|
||||
// to do something with all expressions. All Parser API node types
|
||||
// can be used to identify node types, as well as Expression,
|
||||
// Statement, and ScopeBody, which denote categories of nodes.
|
||||
//
|
||||
// The base argument can be used to pass a custom (recursive)
|
||||
// walker, and state can be used to give this walked an initial
|
||||
// state.
|
||||
exports.simple = function(node, visitors, base, state) {
|
||||
if (!base) base = exports.base;
|
||||
function c(node, st, override) {
|
||||
var type = override || node.type, found = visitors[type];
|
||||
base[type](node, st, c);
|
||||
if (found) found(node, st);
|
||||
}
|
||||
c(node, state);
|
||||
};
|
||||
|
||||
// An ancestor walk builds up an array of ancestor nodes (including
|
||||
// the current node) and passes them to the callback as the state parameter.
|
||||
exports.ancestor = function(node, visitors, base, state) {
|
||||
if (!base) base = exports.base;
|
||||
if (!state) state = [];
|
||||
function c(node, st, override) {
|
||||
var type = override || node.type, found = visitors[type];
|
||||
if (node != st[st.length - 1]) {
|
||||
st = st.slice();
|
||||
st.push(node);
|
||||
}
|
||||
base[type](node, st, c);
|
||||
if (found) found(node, st);
|
||||
}
|
||||
c(node, state);
|
||||
};
|
||||
|
||||
// A recursive walk is one where your functions override the default
|
||||
// walkers. They can modify and replace the state parameter that's
|
||||
// threaded through the walk, and can opt how and whether to walk
|
||||
// their child nodes (by calling their third argument on these
|
||||
// nodes).
|
||||
exports.recursive = function(node, state, funcs, base) {
|
||||
var visitor = funcs ? exports.make(funcs, base) : base;
|
||||
function c(node, st, override) {
|
||||
visitor[override || node.type](node, st, c);
|
||||
}
|
||||
c(node, state);
|
||||
};
|
||||
|
||||
function makeTest(test) {
|
||||
if (typeof test == "string")
|
||||
return function(type) { return type == test; };
|
||||
else if (!test)
|
||||
return function() { return true; };
|
||||
else
|
||||
return test;
|
||||
}
|
||||
|
||||
function Found(node, state) { this.node = node; this.state = state; }
|
||||
|
||||
// Find a node with a given start, end, and type (all are optional,
|
||||
// null can be used as wildcard). Returns a {node, state} object, or
|
||||
// undefined when it doesn't find a matching node.
|
||||
exports.findNodeAt = function(node, start, end, test, base, state) {
|
||||
test = makeTest(test);
|
||||
try {
|
||||
if (!base) base = exports.base;
|
||||
var c = function(node, st, override) {
|
||||
var type = override || node.type;
|
||||
if ((start == null || node.start <= start) &&
|
||||
(end == null || node.end >= end))
|
||||
base[type](node, st, c);
|
||||
if (test(type, node) &&
|
||||
(start == null || node.start == start) &&
|
||||
(end == null || node.end == end))
|
||||
throw new Found(node, st);
|
||||
};
|
||||
c(node, state);
|
||||
} catch (e) {
|
||||
if (e instanceof Found) return e;
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
// Find the innermost node of a given type that contains the given
|
||||
// position. Interface similar to findNodeAt.
|
||||
exports.findNodeAround = function(node, pos, test, base, state) {
|
||||
test = makeTest(test);
|
||||
try {
|
||||
if (!base) base = exports.base;
|
||||
var c = function(node, st, override) {
|
||||
var type = override || node.type;
|
||||
if (node.start > pos || node.end < pos) return;
|
||||
base[type](node, st, c);
|
||||
if (test(type, node)) throw new Found(node, st);
|
||||
};
|
||||
c(node, state);
|
||||
} catch (e) {
|
||||
if (e instanceof Found) return e;
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
// Find the outermost matching node after a given position.
|
||||
exports.findNodeAfter = function(node, pos, test, base, state) {
|
||||
test = makeTest(test);
|
||||
try {
|
||||
if (!base) base = exports.base;
|
||||
var c = function(node, st, override) {
|
||||
if (node.end < pos) return;
|
||||
var type = override || node.type;
|
||||
if (node.start >= pos && test(type, node)) throw new Found(node, st);
|
||||
base[type](node, st, c);
|
||||
};
|
||||
c(node, state);
|
||||
} catch (e) {
|
||||
if (e instanceof Found) return e;
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
// Find the outermost matching node before a given position.
|
||||
exports.findNodeBefore = function(node, pos, test, base, state) {
|
||||
test = makeTest(test);
|
||||
if (!base) base = exports.base;
|
||||
var max;
|
||||
var c = function(node, st, override) {
|
||||
if (node.start > pos) return;
|
||||
var type = override || node.type;
|
||||
if (node.end <= pos && (!max || max.node.end < node.end) && test(type, node))
|
||||
max = new Found(node, st);
|
||||
base[type](node, st, c);
|
||||
};
|
||||
c(node, state);
|
||||
return max;
|
||||
};
|
||||
|
||||
// Used to create a custom walker. Will fill in all missing node
|
||||
// type properties with the defaults.
|
||||
exports.make = function(funcs, base) {
|
||||
if (!base) base = exports.base;
|
||||
var visitor = {};
|
||||
for (var type in base) visitor[type] = base[type];
|
||||
for (var type in funcs) visitor[type] = funcs[type];
|
||||
return visitor;
|
||||
};
|
||||
|
||||
function skipThrough(node, st, c) { c(node, st); }
|
||||
function ignore(_node, _st, _c) {}
|
||||
|
||||
// Node walkers.
|
||||
|
||||
var base = exports.base = {};
|
||||
base.Program = base.BlockStatement = function(node, st, c) {
|
||||
for (var i = 0; i < node.body.length; ++i)
|
||||
c(node.body[i], st, "Statement");
|
||||
};
|
||||
base.Statement = skipThrough;
|
||||
base.EmptyStatement = ignore;
|
||||
base.ExpressionStatement = base.ParenthesizedExpression = function(node, st, c) {
|
||||
c(node.expression, st, "Expression");
|
||||
};
|
||||
base.IfStatement = function(node, st, c) {
|
||||
c(node.test, st, "Expression");
|
||||
c(node.consequent, st, "Statement");
|
||||
if (node.alternate) c(node.alternate, st, "Statement");
|
||||
};
|
||||
base.LabeledStatement = function(node, st, c) {
|
||||
c(node.body, st, "Statement");
|
||||
};
|
||||
base.BreakStatement = base.ContinueStatement = ignore;
|
||||
base.WithStatement = function(node, st, c) {
|
||||
c(node.object, st, "Expression");
|
||||
c(node.body, st, "Statement");
|
||||
};
|
||||
base.SwitchStatement = function(node, st, c) {
|
||||
c(node.discriminant, st, "Expression");
|
||||
for (var i = 0; i < node.cases.length; ++i) {
|
||||
var cs = node.cases[i];
|
||||
if (cs.test) c(cs.test, st, "Expression");
|
||||
for (var j = 0; j < cs.consequent.length; ++j)
|
||||
c(cs.consequent[j], st, "Statement");
|
||||
}
|
||||
};
|
||||
base.ReturnStatement = base.YieldExpression = function(node, st, c) {
|
||||
if (node.argument) c(node.argument, st, "Expression");
|
||||
};
|
||||
base.ThrowStatement = base.SpreadElement = base.RestElement = function(node, st, c) {
|
||||
c(node.argument, st, "Expression");
|
||||
};
|
||||
base.TryStatement = function(node, st, c) {
|
||||
c(node.block, st, "Statement");
|
||||
if (node.handler) c(node.handler.body, st, "ScopeBody");
|
||||
if (node.finalizer) c(node.finalizer, st, "Statement");
|
||||
};
|
||||
base.WhileStatement = function(node, st, c) {
|
||||
c(node.test, st, "Expression");
|
||||
c(node.body, st, "Statement");
|
||||
};
|
||||
base.DoWhileStatement = base.WhileStatement;
|
||||
base.ForStatement = function(node, st, c) {
|
||||
if (node.init) c(node.init, st, "ForInit");
|
||||
if (node.test) c(node.test, st, "Expression");
|
||||
if (node.update) c(node.update, st, "Expression");
|
||||
c(node.body, st, "Statement");
|
||||
};
|
||||
base.ForInStatement = base.ForOfStatement = function(node, st, c) {
|
||||
c(node.left, st, "ForInit");
|
||||
c(node.right, st, "Expression");
|
||||
c(node.body, st, "Statement");
|
||||
};
|
||||
base.ForInit = function(node, st, c) {
|
||||
if (node.type == "VariableDeclaration") c(node, st);
|
||||
else c(node, st, "Expression");
|
||||
};
|
||||
base.DebuggerStatement = ignore;
|
||||
|
||||
base.FunctionDeclaration = function(node, st, c) {
|
||||
c(node, st, "Function");
|
||||
};
|
||||
base.VariableDeclaration = function(node, st, c) {
|
||||
for (var i = 0; i < node.declarations.length; ++i) {
|
||||
var decl = node.declarations[i];
|
||||
if (decl.init) c(decl.init, st, "Expression");
|
||||
}
|
||||
};
|
||||
|
||||
base.Function = function(node, st, c) {
|
||||
c(node.body, st, "ScopeBody");
|
||||
};
|
||||
base.ScopeBody = function(node, st, c) {
|
||||
c(node, st, "Statement");
|
||||
};
|
||||
|
||||
base.Expression = skipThrough;
|
||||
base.ThisExpression = ignore;
|
||||
base.ArrayExpression = base.ArrayPattern = function(node, st, c) {
|
||||
for (var i = 0; i < node.elements.length; ++i) {
|
||||
var elt = node.elements[i];
|
||||
if (elt) c(elt, st, "Expression");
|
||||
}
|
||||
};
|
||||
base.ObjectExpression = base.ObjectPattern = function(node, st, c) {
|
||||
for (var i = 0; i < node.properties.length; ++i)
|
||||
c(node.properties[i], st);
|
||||
};
|
||||
base.FunctionExpression = base.ArrowFunctionExpression = base.FunctionDeclaration;
|
||||
base.SequenceExpression = base.TemplateLiteral = function(node, st, c) {
|
||||
for (var i = 0; i < node.expressions.length; ++i)
|
||||
c(node.expressions[i], st, "Expression");
|
||||
};
|
||||
base.UnaryExpression = base.UpdateExpression = function(node, st, c) {
|
||||
c(node.argument, st, "Expression");
|
||||
};
|
||||
base.BinaryExpression = base.AssignmentExpression = base.AssignmentPattern = base.LogicalExpression = function(node, st, c) {
|
||||
c(node.left, st, "Expression");
|
||||
c(node.right, st, "Expression");
|
||||
};
|
||||
base.ConditionalExpression = function(node, st, c) {
|
||||
c(node.test, st, "Expression");
|
||||
c(node.consequent, st, "Expression");
|
||||
c(node.alternate, st, "Expression");
|
||||
};
|
||||
base.NewExpression = base.CallExpression = function(node, st, c) {
|
||||
c(node.callee, st, "Expression");
|
||||
if (node.arguments) for (var i = 0; i < node.arguments.length; ++i)
|
||||
c(node.arguments[i], st, "Expression");
|
||||
};
|
||||
base.MemberExpression = function(node, st, c) {
|
||||
c(node.object, st, "Expression");
|
||||
if (node.computed) c(node.property, st, "Expression");
|
||||
};
|
||||
base.ExportDeclaration = function (node, st, c) {
|
||||
c(node.declaration, st);
|
||||
};
|
||||
base.ImportDeclaration = function (node, st, c) {
|
||||
node.specifiers.forEach(function (specifier) {
|
||||
c(specifier, st);
|
||||
});
|
||||
};
|
||||
base.ImportSpecifier = base.ImportBatchSpecifier = base.Identifier = base.Literal = ignore;
|
||||
|
||||
base.TaggedTemplateExpression = function(node, st, c) {
|
||||
c(node.tag, st, "Expression");
|
||||
c(node.quasi, st);
|
||||
};
|
||||
base.ClassDeclaration = base.ClassExpression = function(node, st, c) {
|
||||
if (node.superClass) c(node.superClass, st, "Expression");
|
||||
for (var i = 0; i < node.body.body.length; i++)
|
||||
c(node.body.body[i], st);
|
||||
};
|
||||
base.MethodDefinition = base.Property = function(node, st, c) {
|
||||
if (node.computed) c(node.key, st, "Expression");
|
||||
c(node.value, st, "Expression");
|
||||
};
|
||||
base.ComprehensionExpression = function(node, st, c) {
|
||||
for (var i = 0; i < node.blocks.length; i++)
|
||||
c(node.blocks[i].right, st, "Expression");
|
||||
c(node.body, st, "Expression");
|
||||
};
|
||||
|
||||
// NOTE: the stuff below is deprecated, and will be removed when 1.0 is released
|
||||
|
||||
// A custom walker that keeps track of the scope chain and the
|
||||
// variables defined in it.
|
||||
function makeScope(prev, isCatch) {
|
||||
return {vars: Object.create(null), prev: prev, isCatch: isCatch};
|
||||
}
|
||||
function normalScope(scope) {
|
||||
while (scope.isCatch) scope = scope.prev;
|
||||
return scope;
|
||||
}
|
||||
exports.scopeVisitor = exports.make({
|
||||
Function: function(node, scope, c) {
|
||||
var inner = makeScope(scope);
|
||||
for (var i = 0; i < node.params.length; ++i)
|
||||
inner.vars[node.params[i].name] = {type: "argument", node: node.params[i]};
|
||||
if (node.id) {
|
||||
var decl = node.type == "FunctionDeclaration";
|
||||
(decl ? normalScope(scope) : inner).vars[node.id.name] =
|
||||
{type: decl ? "function" : "function name", node: node.id};
|
||||
}
|
||||
c(node.body, inner, "ScopeBody");
|
||||
},
|
||||
TryStatement: function(node, scope, c) {
|
||||
c(node.block, scope, "Statement");
|
||||
if (node.handler) {
|
||||
var inner = makeScope(scope, true);
|
||||
inner.vars[node.handler.param.name] = {type: "catch clause", node: node.handler.param};
|
||||
c(node.handler.body, inner, "ScopeBody");
|
||||
}
|
||||
if (node.finalizer) c(node.finalizer, scope, "Statement");
|
||||
},
|
||||
VariableDeclaration: function(node, scope, c) {
|
||||
var target = normalScope(scope);
|
||||
for (var i = 0; i < node.declarations.length; ++i) {
|
||||
var decl = node.declarations[i];
|
||||
target.vars[decl.id.name] = {type: "var", node: decl.id};
|
||||
if (decl.init) c(decl.init, scope, "Expression");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user