acorn-5.5.3/000077500000000000000000000000001325020065300126225ustar00rootroot00000000000000acorn-5.5.3/.editorconfig000066400000000000000000000001431325020065300152750ustar00rootroot00000000000000root = true [*] indent_style = space indent_size = 2 end_of_line = lf insert_final_newline = true acorn-5.5.3/.gitattributes000066400000000000000000000000161325020065300155120ustar00rootroot00000000000000* text eol=lf acorn-5.5.3/.gitignore000066400000000000000000000000771325020065300146160ustar00rootroot00000000000000.DS_Store node_modules /.tern-port /local /bin/_acorn.js /dist acorn-5.5.3/.npmignore000066400000000000000000000002261325020065300146210ustar00rootroot00000000000000/.tern-port /test /local /rollup /bin/generate-identifier-regex.js /bin/update_authors.sh .editorconfig .gitattributes .tern-project .travis.yml /src acorn-5.5.3/.tern-project000066400000000000000000000000771325020065300152430ustar00rootroot00000000000000{ "plugins": { "node": true, "es_modules": true } }acorn-5.5.3/.travis.yml000066400000000000000000000004551325020065300147370ustar00rootroot00000000000000language: node_js sudo: false matrix: include: - node_js: '0.12' - node_js: '4' - node_js: '5' - node_js: '6' - node_js: '7' - node_js: '8' - node_js: '8' env: TEST_SUITE=test262 script: > if [ "$TEST_SUITE" != "test262" ]; then npm test else npm run test:test262 fi acorn-5.5.3/AUTHORS000066400000000000000000000020101325020065300136630ustar00rootroot00000000000000List of Acorn contributors. Updated before every release. Adrian Heine Adrian Rakovsky Alistair Braidwood Amila Welihinda Andres Suarez Angelo Aparajita Fishman Arian Stolwijk Artem Govorov Boopesh Mahendran Bradley Heinz Brandon Mills Charles Hughes Charmander Conrad Irwin Daniel Tschinder David Bonnet Domenico Matteo ehmicky Felix Maier Forbes Lindesay Gilad Peleg impinball Ingvar Stepanyan Jackson Ray Hamilton Jesse McCarthy Jiaxing Wang Joel Kemp Johannes Herr John-David Dalton Jordan Klassen Jürg Lehni Kai Cataldo keeyipchan Keheliya Gallaba Kevin Irish Kevin Kwok krator laosb Marek Marijn Haverbeke Martin Carlberg Mat Garcia Mathias Bynens Mathieu 'p01' Henri Matthew Bastien Max Schaefer Max Zerzouri Mihai Bazon Mike Rennie naoh Nicholas C. Zakas Nick Fitzgerald Olivier Thomann Oskar Schöldström Paul Harper Peter Rust PlNG Prayag Verma ReadmeCritic r-e-d Richard Gibson Rich Harris Sebastian McKenzie Shahar Soel Sheel Bedi Simen Bekkhus Teddy Katz Timothy Gu Toru Nagashima Victor Homyakov Wexpo Lyu zsjforcn acorn-5.5.3/CHANGELOG.md000066400000000000000000000241631325020065300144410ustar00rootroot00000000000000## 5.5.3 (2018-03-08) ### Bug fixes A _second_ republish of the code in 5.5.1, this time with yarn, to hopefully get valid timestamps. ## 5.5.2 (2018-03-08) ### Bug fixes A republish of the code in 5.5.1 in an attempt to solve an issue with the file timestamps in the npm package being 0. ## 5.5.2 (2018-03-08) ### Bug fixes A republish of the code in 5.5.1 in an attempt to solve an issue with the file timestamps in the npm package being 0. ## 5.5.1 (2018-03-06) ### Bug fixes Fix regression in walker causing property values in object patterns to be walked as expressions. Fix misleading error message for octal escapes in template strings. ## 5.5.0 (2018-02-27) ### Bug fixes Support object spread in the AST walker. ### New features The identifier character categorization is now based on Unicode version 10. Acorn will now validate the content of regular expressions, including new ES9 features. ## 5.4.1 (2018-02-02) ### Bug fixes 5.4.0 somehow accidentally included an old version of walk.js. ## 5.4.0 (2018-02-01) ### Bug fixes Disallow duplicate or escaped flags on regular expressions. Disallow octal escapes in strings in strict mode. ### New features Add support for async iteration. Add support for object spread and rest. ## 5.3.0 (2017-12-28) ### Bug fixes Fix parsing of floating point literals with leading zeroes in loose mode. Allow duplicate property names in object patterns. Don't allow static class methods named `prototype`. Disallow async functions directly under `if` or `else`. Parse right-hand-side of `for`/`of` as an assignment expression. Stricter parsing of `for`/`in`. Don't allow unicode escapes in contextual keywords. ### New features Parsing class members was factored into smaller methods to allow plugins to hook into it. ## 5.2.1 (2017-10-30) ### Bug fixes Fix a token context corruption bug. ## 5.2.0 (2017-10-30) ### Bug fixes Fix token context tracking for `class` and `function` in property-name position. Make sure `%*` isn't parsed as a valid operator. The `full` and `fullAncestor` walkers no longer visit nodes multiple times. Allow shorthand properties `get` and `set` to be followed by default values. Disallow `super` when not in callee or object position. ### New features Support [`directive` property](https://github.com/estree/estree/compare/b3de58c9997504d6fba04b72f76e6dd1619ee4eb...1da8e603237144f44710360f8feb7a9977e905e0) on directive expression statements. ## 5.1.2 (2017-09-04) ### Bug fixes Disable parsing of legacy HTML-style comments in modules. Fix parsing of async methods whose names are keywords. ## 5.1.1 (2017-07-06) ### Bug fixes Fix problem with disambiguating regexp and division after a class. ## 5.1.0 (2017-07-05) ### Bug fixes Fix tokenizing of regexps in an object-desctructuring `for`/`of` loop and after `yield`. Parse zero-prefixed numbers with non-octal digits as decimal. Allow object/array patterns in rest parameters. Don't error when `yield` is used as a property name. Allow `async` as a shorthand object property. Make the ES module version of the loose parser actually work. ### New features Implement the [template literal revision proposal](https://github.com/tc39/proposal-template-literal-revision) for ES9. New walker functions `full` and `fullAncestor`. ## 5.0.3 (2017-04-01) ### Bug fixes Fix spurious duplicate variable definition errors for named functions. ## 5.0.2 (2017-03-30) ### Bug fixes A binary operator after a parenthesized arrow expression is no longer incorrectly treated as an error. ## 5.0.0 (2017-03-28) ### Bug fixes Raise an error for duplicated lexical bindings. Fix spurious error when an assignement expression occurred after a spread expression. Accept regular expressions after `of` (in `for`/`of`), `yield` (in a generator), and braced arrow functions. Allow labels in front or `var` declarations, even in strict mode. ### Breaking changes Parse declarations following `export default` as declaration nodes, not expressions. This means that class and function declarations nodes can now have `null` as their `id`. ## 4.0.11 (2017-02-07) ### Bug fixes Allow all forms of member expressions to be parenthesized as lvalue. ## 4.0.10 (2017-02-07) ### Bug fixes Don't expect semicolons after default-exported functions or classes, even when they are expressions. Check for use of `'use strict'` directives in non-simple parameter functions, even when already in strict mode. ## 4.0.9 (2017-02-06) ### Bug fixes Fix incorrect error raised for parenthesized simple assignment targets, so that `(x) = 1` parses again. ## 4.0.8 (2017-02-03) ### Bug fixes Solve spurious parenthesized pattern errors by temporarily erring on the side of accepting programs that our delayed errors don't handle correctly yet. ## 4.0.7 (2017-02-02) ### Bug fixes Accept invalidly rejected code like `(x).y = 2` again. Don't raise an error when a function _inside_ strict code has a non-simple parameter list. ## 4.0.6 (2017-02-02) ### Bug fixes Fix exponential behavior (manifesting itself as a complete hang for even relatively small source files) introduced by the new 'use strict' check. ## 4.0.5 (2017-02-02) ### Bug fixes Disallow parenthesized pattern expressions. Allow keywords as export names. Don't allow the `async` keyword to be parenthesized. Properly raise an error when a keyword contains a character escape. Allow `"use strict"` to appear after other string literal expressions. Disallow labeled declarations. ## 4.0.4 (2016-12-19) ### Bug fixes Fix issue with loading acorn_loose.js with an AMD loader. Fix crash when `export` was followed by a keyword that can't be exported. ## 4.0.3 (2016-08-16) ### Bug fixes Allow regular function declarations inside single-statement `if` branches in loose mode. Forbid them entirely in strict mode. Properly parse properties named `async` in ES2017 mode. Fix bug where reserved words were broken in ES2017 mode. ## 4.0.2 (2016-08-11) ### Bug fixes Don't ignore period or 'e' characters after octal numbers. Fix broken parsing for call expressions in default parameter values of arrow functions. ## 4.0.1 (2016-08-08) ### Bug fixes Fix false positives in duplicated export name errors. ## 4.0.0 (2016-08-07) ### Breaking changes The default `ecmaVersion` option value is now 7. A number of internal method signatures changed, so plugins might need to be updated. ### Bug fixes The parser now raises errors on duplicated export names. `arguments` and `eval` can now be used in shorthand properties. Duplicate parameter names in non-simple argument lists now always produce an error. ### New features The `ecmaVersion` option now also accepts year-style version numbers (2015, etc). Support for `async`/`await` syntax when `ecmaVersion` is >= 8. Support for trailing commas in call expressions when `ecmaVersion` is >= 8. ## 3.3.0 (2016-07-25) ### Bug fixes Fix bug in tokenizing of regexp operator after a function declaration. Fix parser crash when parsing an array pattern with a hole. ### New features Implement check against complex argument lists in functions that enable strict mode in ES7. ## 3.2.0 (2016-06-07) ### Bug fixes Improve handling of lack of unicode regexp support in host environment. Properly reject shorthand properties whose name is a keyword. Don't crash when the loose parser is called without options object. ### New features Visitors created with `visit.make` now have their base as _prototype_, rather than copying properties into a fresh object. Make it possible to use `visit.ancestor` with a walk state. ## 3.1.0 (2016-04-18) ### Bug fixes Fix issue where the loose parser created invalid TemplateElement nodes for unclosed template literals. Properly tokenize the division operator directly after a function expression. Allow trailing comma in destructuring arrays. ### New features The walker now allows defining handlers for `CatchClause` nodes. ## 3.0.4 (2016-02-25) ### Fixes Allow update expressions as left-hand-side of the ES7 exponential operator. ## 3.0.2 (2016-02-10) ### Fixes Fix bug that accidentally made `undefined` a reserved word when parsing ES7. ## 3.0.0 (2016-02-10) ### Breaking changes The default value of the `ecmaVersion` option is now 6 (used to be 5). Support for comprehension syntax (which was dropped from the draft spec) has been removed. ### Fixes `let` and `yield` are now “contextual keywords”, meaning you can mostly use them as identifiers in ES5 non-strict code. A parenthesized class or function expression after `export default` is now parsed correctly. ### New features When `ecmaVersion` is set to 7, Acorn will parse the exponentiation operator (`**`). The identifier character ranges are now based on Unicode 8.0.0. Plugins can now override the `raiseRecoverable` method to override the way non-critical errors are handled. ## 2.7.0 (2016-01-04) ### Fixes Stop allowing rest parameters in setters. Make sure the loose parser always attaches a `local` property to `ImportNamespaceSpecifier` nodes. Disallow `y` rexexp flag in ES5. Disallow `\00` and `\000` escapes in strict mode. Raise an error when an import name is a reserved word. ## 2.6.4 (2015-11-12) ### Fixes Fix crash in loose parser when parsing invalid object pattern. ### New features Support plugins in the loose parser. ## 2.6.2 (2015-11-10) ### Fixes Don't crash when no options object is passed. ## 2.6.0 (2015-11-09) ### Fixes Add `await` as a reserved word in module sources. Disallow `yield` in a parameter default value for a generator. Forbid using a comma after a rest pattern in an array destructuring. ### New features Support parsing stdin in command-line tool. ## 2.5.2 (2015-10-27) ### Fixes Fix bug where the walker walked an exported `let` statement as an expression. ## 2.5.0 (2015-10-27) ### Fixes Fix tokenizer support in the command-line tool. In the loose parser, don't allow non-string-literals as import sources. Stop allowing `new.target` outside of functions. Remove legacy `guard` and `guardedHandler` properties from try nodes. Stop allowing multiple `__proto__` properties on an object literal in strict mode. Don't allow rest parameters to be non-identifier patterns. Check for duplicate paramter names in arrow functions. acorn-5.5.3/LICENSE000066400000000000000000000020761325020065300136340ustar00rootroot00000000000000Copyright (C) 2012-2018 by various contributors (see AUTHORS) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. acorn-5.5.3/README.md000066400000000000000000000465651325020065300141210ustar00rootroot00000000000000# Acorn [![Build Status](https://travis-ci.org/acornjs/acorn.svg?branch=master)](https://travis-ci.org/acornjs/acorn) [![NPM version](https://img.shields.io/npm/v/acorn.svg)](https://www.npmjs.com/package/acorn) [![CDNJS](https://img.shields.io/cdnjs/v/acorn.svg)](https://cdnjs.com/libraries/acorn) [Author funding status: ![maintainer happiness](https://marijnhaverbeke.nl/fund/status_s.png?force)](https://marijnhaverbeke.nl/fund/) A tiny, fast JavaScript parser, written completely in JavaScript. ## Community Acorn is open source software released under an [MIT license](https://github.com/acornjs/acorn/blob/master/LICENSE). You are welcome to [report bugs](https://github.com/acornjs/acorn/issues) or create pull requests on [github](https://github.com/acornjs/acorn). For questions and discussion, please use the [Tern discussion forum](https://discuss.acornjs.net). ## Installation The easiest way to install acorn is with [`npm`][npm]. [npm]: https://www.npmjs.com/ ```sh npm install acorn ``` Alternately, you can download the source and build acorn yourself: ```sh git clone https://github.com/acornjs/acorn.git cd acorn npm install npm run build ``` ## 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. ### Main parser This is implemented in `dist/acorn.js`, 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 [ESTree spec][estree]. 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. [estree]: https://github.com/estree/estree - **ecmaVersion**: Indicates the ECMAScript version to parse. Must be either 3, 5, 6 (2015), 7 (2016), 8 (2017), or 9 (2018, partial support). This influences support for strict mode, the set of reserved words, and support for new syntax features. Default is 7. **NOTE**: Only 'stage 4' (finalized) ECMAScript features are being implemented by Acorn. - **sourceType**: Indicate the mode the code should be parsed in. Can be either `"script"` or `"module"`. This influences global strict mode and parsing of `import` and `export` declarations. - **onInsertedSemicolon**: If given a callback, that callback will be called whenever a missing semicolon is inserted by the parser. The callback will be given the character offset of the point where the semicolon is inserted as argument, and if `locations` is on, also a `{line, column}` object representing this position. - **onTrailingComma**: Like `onInsertedSemicolon`, but for trailing commas. - **allowReserved**: If `false`, using a reserved word will generate an error. Defaults to `true` for `ecmaVersion` 3, `false` for higher versions. When given the value `"never"`, 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 tokens returned from `tokenizer().getToken()`. 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", "start": Number, "end": Number, // If `locations` option is on: "loc": { "start": {line: Number, column: Number} "end": {line: Number, column: Number} }, // If `ranges` option is on: "range": [Number, Number] } ``` 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 (regardless of the `location` option) 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. **tokenizer**`(input, options)` returns an object with a `getToken` method that can be called repeatedly to get the next token, 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). When the token's type is `tokTypes.eof`, you should stop calling the method, since it will keep returning that same token forever. In ES6 environment, returned result can be used as any other protocol-compliant iterable: ```javascript for (let token of acorn.tokenizer(str)) { // iterate over the tokens } // transform code to array of tokens: var tokens = [...acorn.tokenizer(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/estools/escodegen ### dist/acorn_loose.js ### This file implements an error-tolerant parser. It exposes a single function. The loose parser is accessible in node.js via `require("acorn/dist/acorn_loose")`. **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. ### dist/walk.js ### Implements an abstract syntax tree walker. Will store its interface in `acorn.walk` when loaded 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 [ESTree spec][estree]. 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 is to track scope at each point in the tree.) ```js const acorn = require("acorn") const walk = require("acorn/dist/walk") walk.simple(acorn.parse("let x = 10"), { Literal(node) { console.log(`Found a literal: ${node.value}`) } }) ``` **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 the callbacks as a third parameter. ```js const acorn = require("acorn") const walk = require("acorn/dist/walk") walk.ancestor(acorn.parse("foo('hi')"), { Literal(_, ancestors) { console.log("This literal's ancestors are:", ancestors.map(n => n.type)) } }) ``` **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`. **full**`(node, callback, base, state)` does a 'full' walk over a tree, calling the callback with the arguments (node, state, type) for each node **fullAncestor**`(node, callback, base, state)` does a 'full' walk over a tree, building up an array of ancestor nodes (including the current node) and passing the array to the callbacks as a third parameter. ```js const acorn = require("acorn") const walk = require("acorn/dist/walk") walk.full(acorn.parse("1 + 1"), node => { console.log(`There's a ${node.type} node at ${node.ch}`) }) ``` **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` and `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|--ecma7|--ecma8|--ecma9`: Sets the ECMAScript version to parse. Default is version 7. - `--module`: Sets the parsing mode to `"module"`. Is set to `"script"` otherwise. - `--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. - `--allow-hash-bang`: If the code starts with the characters #! (as in a shellscript), the first line will be treated as a comment. - `--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. ## Build system Acorn is written in ECMAScript 6, as a set of small modules, in the project's `src` directory, and compiled down to bigger ECMAScript 3 files in `dist` using [Browserify](http://browserify.org) and [Babel](http://babeljs.io/). If you are already using Babel, you can consider including the modules directly. The command-line test runner (`npm test`) uses the ES6 modules. The browser-based test page (`test/index.html`) uses the compiled modules. The `bin/build-acorn.js` script builds the latter from the former. If you are working on Acorn, you'll probably want to try the code out directly, without an intermediate build step. In your scripts, you can register the Babel require shim like this: require("babel-core/register") That will allow you to directly `require` the ES6 modules. ## Plugins Acorn is designed support allow plugins which, within reasonable bounds, redefine the way the parser works. Plugins can add new token types and new tokenizer contexts (if necessary), and extend methods in the parser object. This is not a clean, elegant API—using it requires an understanding of Acorn's internals, and plugins are likely to break whenever those internals are significantly changed. But still, it is _possible_, in this way, to create parsers for JavaScript dialects without forking all of Acorn. And in principle it is even possible to combine such plugins, so that if you have, for example, a plugin for parsing types and a plugin for parsing JSX-style XML literals, you could load them both and parse code with both JSX tags and types. A plugin should register itself by adding a property to `acorn.plugins`, which holds a function. Calling `acorn.parse`, a `plugins` option can be passed, holding an object mapping plugin names to configuration values (or just `true` for plugins that don't take options). After the parser object has been created, the initialization functions for the chosen plugins are called with `(parser, configValue)` arguments. They are expected to use the `parser.extend` method to extend parser methods. For example, the `readToken` method could be extended like this: ```javascript parser.extend("readToken", function(nextMethod) { return function(code) { console.log("Reading a token!") return nextMethod.call(this, code) } }) ``` The `nextMethod` argument passed to `extend`'s second argument is the previous value of this method, and should usually be called through to whenever the extended method does not handle the call itself. Similarly, the loose parser allows plugins to register themselves via `acorn.pluginsLoose`. The extension mechanism is the same as for the normal parser: ```javascript looseParser.extend("readToken", function(nextMethod) { return function() { console.log("Reading a token in the loose parser!") return nextMethod.call(this) } }) ``` ### Existing plugins - [`acorn-jsx`](https://github.com/RReverser/acorn-jsx): Parse [Facebook JSX syntax extensions](https://github.com/facebook/jsx) - [`acorn-objj`](https://github.com/cappuccino/acorn-objj): [Objective-J](http://www.cappuccino-project.org/learn/objective-j.html) language parser built as Acorn plugin Plugins for ECMAScript proposals: - [`acorn-stage3`](https://github.com/acornjs/acorn-stage3): Parse most stage 3 proposals, bundling: - [`acorn-async-iteration`](https://github.com/acornjs/acorn-async-iteration): Parse [async iteration proposal](https://github.com/tc39/proposal-async-iteration) - [`acorn-bigint`](https://github.com/acornjs/acorn-bigint): Parse [BigInt proposal](https://github.com/tc39/proposal-bigint) - [`acorn-class-fields`](https://github.com/acornjs/acorn-class-fields): Parse [class fields proposal](https://github.com/tc39/proposal-class-fields) - [`acorn-dynamic-import`](https://github.com/kesne/acorn-dynamic-import): Parse [import() proposal](https://github.com/tc39/proposal-dynamic-import) - [`acorn-import-meta`](https://github.com/acornjs/acorn-import-meta): Parse [import.meta proposal](https://github.com/tc39/proposal-import-meta) - [`acorn-numeric-separator`](https://github.com/acornjs/acorn-numeric-separator): Parse [numeric separator proposal](https://github.com/tc39/proposal-numeric-separator) - [`acorn-optional-catch-binding`](https://github.com/acornjs/acorn-optional-catch-binding): Parse [optional catch binding proposal](https://github.com/tc39/proposal-optional-catch-binding) - [`acorn-private-methods`](https://github.com/acornjs/acorn-private-methods): parse [private methods, getters and setters proposal](https://github.com/tc39/proposal-private-methods) - [`acorn5-object-spread`](https://github.com/adrianheine/acorn5-object-spread): Parse [Object Rest/Spread Properties proposal](https://github.com/tc39/proposal-object-rest-spread) - [`acorn-object-rest-spread`](https://github.com/victor-homyakov/acorn-object-rest-spread): Parse [Object Rest/Spread Properties proposal](https://github.com/tc39/proposal-object-rest-spread) - [`acorn-es7`](https://github.com/angelozerr/acorn-es7): Parse [decorator syntax proposal](https://github.com/wycats/javascript-decorators) - [`acorn-static-class-property-initializer`](https://github.com/victor-homyakov/acorn-static-class-property-initializer): Partial support for static class properties from [ES Class Fields & Static Properties Proposal](https://github.com/tc39/proposal-class-public-fields) to support static property initializers in [React components written as ES6+ classes](https://babeljs.io/blog/2015/06/07/react-on-es6-plus) acorn-5.5.3/bin/000077500000000000000000000000001325020065300133725ustar00rootroot00000000000000acorn-5.5.3/bin/acorn000077500000000000000000000000731325020065300144220ustar00rootroot00000000000000#!/usr/bin/env node 'use strict'; require('./_acorn.js'); acorn-5.5.3/bin/generate-identifier-regex.js000066400000000000000000000035151325020065300207560ustar00rootroot00000000000000'use strict'; // Which Unicode version should be used? var pkg = require('../package.json'); var dependencies = Object.keys(pkg.devDependencies); var unicodeVersion = dependencies.find((name) => /^unicode-\d/.test(name)); var start = require(unicodeVersion + '/Binary_Property/ID_Start/code-points.js') .filter(function(ch) { return ch > 0x7f; }); var last = -1; var cont = [0x200c, 0x200d].concat(require(unicodeVersion + '/Binary_Property/ID_Continue/code-points.js') .filter(function(ch) { return ch > 0x7f && search(start, ch, last + 1) == -1; })); function search(arr, ch, starting) { for (var i = starting; arr[i] <= ch && i < arr.length; last = i++) if (arr[i] === ch) return i; return -1; } function pad(str, width) { while (str.length < width) str = "0" + str; return str; } function esc(code) { var hex = code.toString(16); if (hex.length <= 2) return "\\x" + pad(hex, 2); else return "\\u" + pad(hex, 4); } function generate(chars) { var astral = [], re = ""; for (var i = 0, at = 0x10000; i < chars.length; i++) { var from = chars[i], to = from; while (i < chars.length - 1 && chars[i + 1] == to + 1) { i++; to++; } if (to <= 0xffff) { if (from == to) re += esc(from); else if (from + 1 == to) re += esc(from) + esc(to); else re += esc(from) + "-" + esc(to); } else { astral.push(from - at, to - from); at = to; } } return {nonASCII: re, astral: astral}; } var startData = generate(start), contData = generate(cont); console.log("let nonASCIIidentifierStartChars = \"" + startData.nonASCII + "\""); console.log("let nonASCIIidentifierChars = \"" + contData.nonASCII + "\""); console.log("const astralIdentifierStartCodes = " + JSON.stringify(startData.astral)); console.log("const astralIdentifierCodes = " + JSON.stringify(contData.astral)); acorn-5.5.3/bin/run_test262.js000066400000000000000000000012401325020065300160220ustar00rootroot00000000000000const fs = require("fs") const path = require("path") const run = require("test262-parser-runner") const parse = require("..").parse const unsupportedFeatures = [ "BigInt", "class-fields", "class-fields-private", "class-fields-public", "numeric-separator-literal", "optional-catch-binding" ]; run( (content, {sourceType}) => parse(content, {sourceType, ecmaVersion: 9}), { testsDirectory: path.dirname(require.resolve("test262/package.json")), skip: test => (test.attrs.features && unsupportedFeatures.some(f => test.attrs.features.includes(f))), whitelist: fs.readFileSync("./bin/test262.whitelist", "utf8").split("\n").filter(v => v) } ) acorn-5.5.3/bin/test262.whitelist000066400000000000000000001173151325020065300165510ustar00rootroot00000000000000annexB/language/function-code/block-decl-func-no-skip-try.js (default) annexB/language/function-code/block-decl-func-skip-early-err-block.js (default) annexB/language/function-code/block-decl-func-skip-early-err.js (default) annexB/language/function-code/block-decl-func-skip-early-err-switch.js (default) annexB/language/function-code/block-decl-func-skip-early-err-try.js (default) annexB/language/function-code/if-decl-else-decl-a-func-no-skip-try.js (default) annexB/language/function-code/if-decl-else-decl-a-func-skip-early-err-block.js (default) annexB/language/function-code/if-decl-else-decl-a-func-skip-early-err.js (default) annexB/language/function-code/if-decl-else-decl-a-func-skip-early-err-switch.js (default) annexB/language/function-code/if-decl-else-decl-a-func-skip-early-err-try.js (default) annexB/language/function-code/if-decl-else-decl-b-func-no-skip-try.js (default) annexB/language/function-code/if-decl-else-decl-b-func-skip-early-err-block.js (default) annexB/language/function-code/if-decl-else-decl-b-func-skip-early-err.js (default) annexB/language/function-code/if-decl-else-decl-b-func-skip-early-err-switch.js (default) annexB/language/function-code/if-decl-else-decl-b-func-skip-early-err-try.js (default) annexB/language/function-code/if-decl-else-stmt-func-no-skip-try.js (default) annexB/language/function-code/if-decl-else-stmt-func-skip-early-err-block.js (default) annexB/language/function-code/if-decl-else-stmt-func-skip-early-err.js (default) annexB/language/function-code/if-decl-else-stmt-func-skip-early-err-switch.js (default) annexB/language/function-code/if-decl-else-stmt-func-skip-early-err-try.js (default) annexB/language/function-code/if-decl-no-else-func-no-skip-try.js (default) annexB/language/function-code/if-decl-no-else-func-skip-early-err-block.js (default) annexB/language/function-code/if-decl-no-else-func-skip-early-err.js (default) annexB/language/function-code/if-decl-no-else-func-skip-early-err-switch.js (default) annexB/language/function-code/if-decl-no-else-func-skip-early-err-try.js (default) annexB/language/function-code/if-stmt-else-decl-func-no-skip-try.js (default) annexB/language/function-code/if-stmt-else-decl-func-skip-early-err-block.js (default) annexB/language/function-code/if-stmt-else-decl-func-skip-early-err.js (default) annexB/language/function-code/if-stmt-else-decl-func-skip-early-err-switch.js (default) annexB/language/function-code/if-stmt-else-decl-func-skip-early-err-try.js (default) annexB/language/function-code/switch-case-func-no-skip-try.js (default) annexB/language/function-code/switch-case-func-skip-early-err-block.js (default) annexB/language/function-code/switch-case-func-skip-early-err.js (default) annexB/language/function-code/switch-case-func-skip-early-err-switch.js (default) annexB/language/function-code/switch-case-func-skip-early-err-try.js (default) annexB/language/function-code/switch-dflt-func-no-skip-try.js (default) annexB/language/function-code/switch-dflt-func-skip-early-err-block.js (default) annexB/language/function-code/switch-dflt-func-skip-early-err.js (default) annexB/language/function-code/switch-dflt-func-skip-early-err-switch.js (default) annexB/language/function-code/switch-dflt-func-skip-early-err-try.js (default) annexB/language/global-code/block-decl-global-no-skip-try.js (default) annexB/language/global-code/block-decl-global-skip-early-err-block.js (default) annexB/language/global-code/block-decl-global-skip-early-err.js (default) annexB/language/global-code/block-decl-global-skip-early-err-switch.js (default) annexB/language/global-code/block-decl-global-skip-early-err-try.js (default) annexB/language/global-code/if-decl-else-decl-a-global-no-skip-try.js (default) annexB/language/global-code/if-decl-else-decl-a-global-skip-early-err-block.js (default) annexB/language/global-code/if-decl-else-decl-a-global-skip-early-err.js (default) annexB/language/global-code/if-decl-else-decl-a-global-skip-early-err-switch.js (default) annexB/language/global-code/if-decl-else-decl-a-global-skip-early-err-try.js (default) annexB/language/global-code/if-decl-else-decl-b-global-no-skip-try.js (default) annexB/language/global-code/if-decl-else-decl-b-global-skip-early-err-block.js (default) annexB/language/global-code/if-decl-else-decl-b-global-skip-early-err.js (default) annexB/language/global-code/if-decl-else-decl-b-global-skip-early-err-switch.js (default) annexB/language/global-code/if-decl-else-decl-b-global-skip-early-err-try.js (default) annexB/language/global-code/if-decl-else-stmt-global-no-skip-try.js (default) annexB/language/global-code/if-decl-else-stmt-global-skip-early-err-block.js (default) annexB/language/global-code/if-decl-else-stmt-global-skip-early-err.js (default) annexB/language/global-code/if-decl-else-stmt-global-skip-early-err-switch.js (default) annexB/language/global-code/if-decl-else-stmt-global-skip-early-err-try.js (default) annexB/language/global-code/if-decl-no-else-global-no-skip-try.js (default) annexB/language/global-code/if-decl-no-else-global-skip-early-err-block.js (default) annexB/language/global-code/if-decl-no-else-global-skip-early-err.js (default) annexB/language/global-code/if-decl-no-else-global-skip-early-err-switch.js (default) annexB/language/global-code/if-decl-no-else-global-skip-early-err-try.js (default) annexB/language/global-code/if-stmt-else-decl-global-no-skip-try.js (default) annexB/language/global-code/if-stmt-else-decl-global-skip-early-err-block.js (default) annexB/language/global-code/if-stmt-else-decl-global-skip-early-err.js (default) annexB/language/global-code/if-stmt-else-decl-global-skip-early-err-switch.js (default) annexB/language/global-code/if-stmt-else-decl-global-skip-early-err-try.js (default) annexB/language/global-code/switch-case-global-no-skip-try.js (default) annexB/language/global-code/switch-case-global-skip-early-err-block.js (default) annexB/language/global-code/switch-case-global-skip-early-err.js (default) annexB/language/global-code/switch-case-global-skip-early-err-switch.js (default) annexB/language/global-code/switch-case-global-skip-early-err-try.js (default) annexB/language/global-code/switch-dflt-global-no-skip-try.js (default) annexB/language/global-code/switch-dflt-global-skip-early-err-block.js (default) annexB/language/global-code/switch-dflt-global-skip-early-err.js (default) annexB/language/global-code/switch-dflt-global-skip-early-err-switch.js (default) annexB/language/global-code/switch-dflt-global-skip-early-err-try.js (default) annexB/language/statements/try/catch-redeclared-for-in-var.js (default) annexB/language/statements/try/catch-redeclared-for-in-var.js (strict mode) annexB/language/statements/try/catch-redeclared-for-var.js (default) annexB/language/statements/try/catch-redeclared-for-var.js (strict mode) annexB/language/statements/try/catch-redeclared-var-statement-captured.js (default) annexB/language/statements/try/catch-redeclared-var-statement-captured.js (strict mode) annexB/language/statements/try/catch-redeclared-var-statement.js (default) annexB/language/statements/try/catch-redeclared-var-statement.js (strict mode) language/block-scope/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-async-function-declaration.js (default) language/block-scope/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-async-function-declaration.js (strict mode) language/block-scope/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/block-scope/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/block-scope/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-function-declaration.js (default) language/block-scope/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-function-declaration.js (strict mode) language/block-scope/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-generator-declaration.js (default) language/block-scope/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-generator-declaration.js (strict mode) language/block-scope/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-var-declaration.js (default) language/block-scope/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-var-declaration.js (strict mode) language/block-scope/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-async-generator-declaration.js (default) language/block-scope/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-async-generator-declaration.js (strict mode) language/block-scope/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-async-function-declaration.js (default) language/block-scope/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-async-function-declaration.js (strict mode) language/block-scope/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-async-generator-declaration.js (default) language/block-scope/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-async-generator-declaration.js (strict mode) language/block-scope/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/block-scope/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/block-scope/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-function-declaration.js (default) language/block-scope/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-function-declaration.js (strict mode) language/block-scope/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-generator-declaration.js (default) language/block-scope/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-generator-declaration.js (strict mode) language/block-scope/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-var-declaration.js (default) language/block-scope/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-var-declaration.js (strict mode) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-async-generator-declaration.js (default) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-async-generator-declaration.js (strict mode) language/block-scope/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-async-generator-declaration.js (default) language/block-scope/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-async-generator-declaration.js (strict mode) language/block-scope/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-async-generator-declaration.js (default) language/block-scope/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-async-generator-declaration.js (strict mode) language/block-scope/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-async-generator-declaration.js (default) language/block-scope/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-async-generator-declaration.js (strict mode) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-async-function-declaration.js (default) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-async-function-declaration.js (strict mode) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-const-declaration.js (default) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-const-declaration.js (strict mode) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-function-declaration.js (default) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-function-declaration.js (strict mode) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-generator-declaration.js (default) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-generator-declaration.js (strict mode) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-let-declaration.js (default) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-let-declaration.js (strict mode) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-var-declaration.js (default) language/block-scope/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-var-declaration.js (strict mode) language/block-scope/syntax/redeclaration/const-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/block-scope/syntax/redeclaration/const-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/block-scope/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-async-function-declaration.js (default) language/block-scope/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-async-function-declaration.js (strict mode) language/block-scope/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/block-scope/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/block-scope/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-function-declaration.js (strict mode) language/block-scope/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-generator-declaration.js (default) language/block-scope/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-generator-declaration.js (strict mode) language/block-scope/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-var-declaration.js (default) language/block-scope/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-var-declaration.js (strict mode) language/block-scope/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-async-function-declaration.js (default) language/block-scope/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-async-function-declaration.js (strict mode) language/block-scope/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/block-scope/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/block-scope/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-function-declaration.js (default) language/block-scope/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-function-declaration.js (strict mode) language/block-scope/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-generator-declaration.js (default) language/block-scope/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-generator-declaration.js (strict mode) language/block-scope/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-var-declaration.js (default) language/block-scope/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-var-declaration.js (strict mode) language/block-scope/syntax/redeclaration/let-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/block-scope/syntax/redeclaration/let-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/block-scope/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-async-function-declaration.js (default) language/block-scope/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-async-function-declaration.js (strict mode) language/block-scope/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/block-scope/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/block-scope/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-function-declaration.js (default) language/block-scope/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-function-declaration.js (strict mode) language/block-scope/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-generator-declaration.js (default) language/block-scope/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-generator-declaration.js (strict mode) language/expressions/async-arrow-function/early-errors-arrow-await-in-formals-default.js (default) language/expressions/async-arrow-function/early-errors-arrow-await-in-formals-default.js (strict mode) language/expressions/async-arrow-function/early-errors-arrow-body-contains-super-call.js (default) language/expressions/async-arrow-function/early-errors-arrow-body-contains-super-call.js (strict mode) language/expressions/async-arrow-function/early-errors-arrow-body-contains-super-property.js (default) language/expressions/async-arrow-function/early-errors-arrow-body-contains-super-property.js (strict mode) language/expressions/async-function/early-errors-expression-body-contains-super-call.js (default) language/expressions/async-function/early-errors-expression-body-contains-super-call.js (strict mode) language/expressions/async-function/early-errors-expression-body-contains-super-property.js (default) language/expressions/async-function/early-errors-expression-body-contains-super-property.js (strict mode) language/expressions/async-function/early-errors-expression-formals-contains-super-call.js (default) language/expressions/async-function/early-errors-expression-formals-contains-super-call.js (strict mode) language/expressions/async-function/early-errors-expression-formals-contains-super-property.js (default) language/expressions/async-function/early-errors-expression-formals-contains-super-property.js (strict mode) language/expressions/class/method-param-dflt-yield.js (default) language/expressions/class/static-method-param-dflt-yield.js (default) language/expressions/function/early-body-super-call.js (default) language/expressions/function/early-body-super-call.js (strict mode) language/expressions/function/early-body-super-prop.js (default) language/expressions/function/early-body-super-prop.js (strict mode) language/expressions/function/early-params-super-call.js (default) language/expressions/function/early-params-super-call.js (strict mode) language/expressions/function/early-params-super-prop.js (default) language/expressions/function/early-params-super-prop.js (strict mode) language/expressions/object/method-definition/early-errors-object-method-body-contains-super-call.js (default) language/expressions/object/method-definition/early-errors-object-method-body-contains-super-call.js (strict mode) language/expressions/object/method-definition/early-errors-object-method-duplicate-parameters.js (default) language/expressions/object/method-definition/early-errors-object-method-formals-contains-super-call.js (default) language/expressions/object/method-definition/early-errors-object-method-formals-contains-super-call.js (strict mode) language/expressions/object/method-definition/generator-super-call-body.js (default) language/expressions/object/method-definition/generator-super-call-body.js (strict mode) language/expressions/object/method-definition/generator-super-call-param.js (default) language/expressions/object/method-definition/generator-super-call-param.js (strict mode) language/expressions/object/prop-def-invalid-async-prefix.js (default) language/expressions/object/prop-def-invalid-async-prefix.js (strict mode) language/expressions/yield/in-iteration-stmt.js (default) language/expressions/yield/in-iteration-stmt.js (strict mode) language/expressions/yield/star-in-iteration-stmt.js (default) language/expressions/yield/star-in-iteration-stmt.js (strict mode) language/global-code/new.target-arrow.js (default) language/global-code/new.target-arrow.js (strict mode) language/global-code/super-call-arrow.js (default) language/global-code/super-call-arrow.js (strict mode) language/global-code/super-prop-arrow.js (default) language/global-code/super-prop-arrow.js (strict mode) language/module-code/early-export-global.js (default) language/module-code/early-export-global.js (strict mode) language/module-code/early-export-unresolvable.js (default) language/module-code/early-export-unresolvable.js (strict mode) language/module-code/parse-err-hoist-lex-fun.js (default) language/module-code/parse-err-hoist-lex-fun.js (strict mode) language/module-code/parse-err-hoist-lex-gen.js (default) language/module-code/parse-err-hoist-lex-gen.js (strict mode) language/statements/async-function/early-errors-declaration-body-contains-super-call.js (default) language/statements/async-function/early-errors-declaration-body-contains-super-call.js (strict mode) language/statements/async-function/early-errors-declaration-body-contains-super-property.js (default) language/statements/async-function/early-errors-declaration-body-contains-super-property.js (strict mode) language/statements/async-function/early-errors-declaration-formals-contains-super-call.js (default) language/statements/async-function/early-errors-declaration-formals-contains-super-call.js (strict mode) language/statements/async-function/early-errors-declaration-formals-contains-super-property.js (default) language/statements/async-function/early-errors-declaration-formals-contains-super-property.js (strict mode) language/expressions/async-generator/early-errors-expression-body-contains-super-call.js (default) language/expressions/async-generator/early-errors-expression-body-contains-super-call.js (strict mode) language/expressions/async-generator/early-errors-expression-body-contains-super-property.js (default) language/expressions/async-generator/early-errors-expression-body-contains-super-property.js (strict mode) language/expressions/async-generator/early-errors-expression-formals-contains-super-call.js (default) language/expressions/async-generator/early-errors-expression-formals-contains-super-call.js (strict mode) language/expressions/async-generator/early-errors-expression-formals-contains-super-property.js (default) language/expressions/async-generator/early-errors-expression-formals-contains-super-property.js (strict mode) language/statements/class/definition/early-errors-class-method-arguments-in-formal-parameters.js (default) language/statements/class/definition/early-errors-class-method-body-contains-super-call.js (default) language/statements/class/definition/early-errors-class-method-body-contains-super-call.js (strict mode) language/statements/class/definition/early-errors-class-method-duplicate-parameters.js (default) language/statements/class/definition/early-errors-class-method-eval-in-formal-parameters.js (default) language/statements/class/definition/early-errors-class-method-formals-contains-super-call.js (default) language/statements/class/definition/early-errors-class-method-formals-contains-super-call.js (strict mode) language/statements/class/definition/methods-gen-yield-as-function-expression-binding-identifier.js (default) language/statements/class/definition/methods-gen-yield-as-identifier-in-nested-function.js (default) language/statements/class/method-param-yield.js (default) language/statements/class/static-method-param-yield.js (default) language/statements/class/strict-mode/with.js (default) language/statements/class/syntax/early-errors/class-body-has-direct-super-missing-class-heritage.js (default) language/statements/class/syntax/early-errors/class-body-has-direct-super-missing-class-heritage.js (strict mode) language/statements/class/syntax/early-errors/class-body-method-contains-direct-super.js (default) language/statements/class/syntax/early-errors/class-body-method-contains-direct-super.js (strict mode) language/statements/class/syntax/early-errors/class-body-special-method-generator-contains-direct-super.js (default) language/statements/class/syntax/early-errors/class-body-special-method-generator-contains-direct-super.js (strict mode) language/statements/class/syntax/early-errors/class-body-special-method-get-contains-direct-super.js (default) language/statements/class/syntax/early-errors/class-body-special-method-get-contains-direct-super.js (strict mode) language/statements/class/syntax/early-errors/class-body-special-method-set-contains-direct-super.js (default) language/statements/class/syntax/early-errors/class-body-special-method-set-contains-direct-super.js (strict mode) language/statements/class/syntax/early-errors/class-body-static-method-contains-direct-super.js (default) language/statements/class/syntax/early-errors/class-body-static-method-contains-direct-super.js (strict mode) language/statements/class/syntax/early-errors/class-body-static-method-get-contains-direct-super.js (default) language/statements/class/syntax/early-errors/class-body-static-method-get-contains-direct-super.js (strict mode) language/statements/class/syntax/early-errors/class-body-static-method-set-contains-direct-super.js (default) language/statements/class/syntax/early-errors/class-body-static-method-set-contains-direct-super.js (strict mode) language/statements/class/syntax/early-errors/class-definition-evaluation-block-duplicate-binding.js (default) language/statements/class/syntax/early-errors/class-definition-evaluation-block-duplicate-binding.js (strict mode) language/statements/class/syntax/early-errors/class-definition-evaluation-scriptbody-duplicate-binding.js (default) language/statements/class/syntax/early-errors/class-definition-evaluation-scriptbody-duplicate-binding.js (strict mode) language/statements/const/syntax/const-declaring-let-split-across-two-lines.js (default) language/statements/do-while/labelled-fn-stmt.js (default) language/statements/for/head-let-bound-names-in-stmt.js (default) language/statements/for/head-let-bound-names-in-stmt.js (strict mode) language/statements/for-in/head-const-bound-names-in-stmt.js (default) language/statements/for-in/head-const-bound-names-in-stmt.js (strict mode) language/statements/for-in/head-const-bound-names-let.js (default) language/statements/for-in/head-let-bound-names-in-stmt.js (default) language/statements/for-in/head-let-bound-names-in-stmt.js (strict mode) language/statements/for-in/head-let-bound-names-let.js (default) language/statements/for-in/labelled-fn-stmt-const.js (default) language/statements/for-in/labelled-fn-stmt-let.js (default) language/statements/for-in/labelled-fn-stmt-lhs.js (default) language/statements/for-in/labelled-fn-stmt-var.js (default) language/statements/for-in/let-block-with-newline.js (default) language/statements/for-in/let-identifier-with-newline.js (default) language/statements/for/labelled-fn-stmt-expr.js (default) language/statements/for/labelled-fn-stmt-let.js (default) language/statements/for/labelled-fn-stmt-var.js (default) language/statements/for/let-block-with-newline.js (default) language/statements/for/let-identifier-with-newline.js (default) language/statements/for-of/head-const-bound-names-in-stmt.js (default) language/statements/for-of/head-const-bound-names-in-stmt.js (strict mode) language/statements/for-of/head-const-bound-names-let.js (default) language/statements/for-of/head-let-bound-names-in-stmt.js (default) language/statements/for-of/head-let-bound-names-in-stmt.js (strict mode) language/statements/for-of/head-let-bound-names-let.js (default) language/statements/for-of/labelled-fn-stmt-const.js (default) language/statements/for-of/labelled-fn-stmt-let.js (default) language/statements/for-of/labelled-fn-stmt-lhs.js (default) language/statements/for-of/labelled-fn-stmt-var.js (default) language/statements/for-of/let-block-with-newline.js (default) language/statements/for-of/let-identifier-with-newline.js (default) language/statements/for-await-of/let-block-with-newline.js (default) language/statements/for-await-of/let-identifier-with-newline.js (default) language/statements/function/early-body-super-call.js (default) language/statements/function/early-body-super-call.js (strict mode) language/statements/function/early-body-super-prop.js (default) language/statements/function/early-body-super-prop.js (strict mode) language/statements/function/early-params-super-call.js (default) language/statements/function/early-params-super-call.js (strict mode) language/statements/function/early-params-super-prop.js (default) language/statements/function/early-params-super-prop.js (strict mode) language/statements/if/if-gen-else-gen.js (default) language/statements/if/if-gen-else-stmt.js (default) language/statements/if/if-gen-no-else.js (default) language/statements/if/if-stmt-else-gen.js (default) language/statements/if/labelled-fn-stmt-first.js (default) language/statements/if/labelled-fn-stmt-lone.js (default) language/statements/if/labelled-fn-stmt-second.js (default) language/statements/if/let-block-with-newline.js (default) language/statements/if/let-identifier-with-newline.js (default) language/statements/labeled/decl-async-function.js (default) language/statements/labeled/let-block-with-newline.js (default) language/statements/labeled/let-identifier-with-newline.js (default) language/statements/let/syntax/identifier-let-disallowed-as-boundname.js (default) language/statements/let/syntax/let-let-declaration-split-across-two-lines.js (default) language/statements/let/syntax/let-let-declaration-with-initializer-split-across-two-lines.js (default) language/statements/switch/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-async-function-declaration.js (default) language/statements/switch/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-async-function-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/statements/switch/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-function-declaration.js (default) language/statements/switch/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-function-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-generator-declaration.js (default) language/statements/switch/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-generator-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-var-declaration.js (default) language/statements/switch/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-var-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-async-generator-declaration.js (default) language/statements/switch/syntax/redeclaration/async-function-declaration-attempt-to-redeclare-with-async-generator-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-async-function-declaration.js (default) language/statements/switch/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-async-function-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-async-generator-declaration.js (default) language/statements/switch/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-async-generator-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/statements/switch/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-function-declaration.js (default) language/statements/switch/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-function-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-generator-declaration.js (default) language/statements/switch/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-generator-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-var-declaration.js (default) language/statements/switch/syntax/redeclaration/async-generator-declaration-attempt-to-redeclare-with-var-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-async-generator-declaration.js (default) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-async-generator-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-async-generator-declaration.js (default) language/statements/switch/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-async-generator-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-async-generator-declaration.js (default) language/statements/switch/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-async-generator-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-async-generator-declaration.js (default) language/statements/switch/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-async-generator-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-async-function-declaration.js (default) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-async-function-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-const-declaration.js (default) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-const-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-function-declaration.js (default) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-function-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-generator-declaration.js (default) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-generator-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-let-declaration.js (default) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-let-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-var-declaration.js (default) language/statements/switch/syntax/redeclaration/class-declaration-attempt-to-redeclare-with-var-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/const-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/statements/switch/syntax/redeclaration/const-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-async-function-declaration.js (default) language/statements/switch/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-async-function-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/statements/switch/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-function-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-generator-declaration.js (default) language/statements/switch/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-generator-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-var-declaration.js (default) language/statements/switch/syntax/redeclaration/function-declaration-attempt-to-redeclare-with-var-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-async-function-declaration.js (default) language/statements/switch/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-async-function-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/statements/switch/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-function-declaration.js (default) language/statements/switch/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-function-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-generator-declaration.js (default) language/statements/switch/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-generator-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-var-declaration.js (default) language/statements/switch/syntax/redeclaration/generator-declaration-attempt-to-redeclare-with-var-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/let-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/statements/switch/syntax/redeclaration/let-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-async-function-declaration.js (default) language/statements/switch/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-async-function-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-class-declaration.js (default) language/statements/switch/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-class-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-function-declaration.js (default) language/statements/switch/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-function-declaration.js (strict mode) language/statements/switch/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-generator-declaration.js (default) language/statements/switch/syntax/redeclaration/var-declaration-attempt-to-redeclare-with-generator-declaration.js (strict mode) language/statements/while/labelled-fn-stmt.js (default) language/statements/while/let-block-with-newline.js (default) language/statements/while/let-identifier-with-newline.js (default) language/statements/with/labelled-fn-stmt.js (default) language/statements/with/let-block-with-newline.js (default) language/statements/with/let-identifier-with-newline.js (default) language/white-space/mongolian-vowel-separator.js (default) language/white-space/mongolian-vowel-separator.js (strict mode) acorn-5.5.3/bin/update_authors.sh000077500000000000000000000003551325020065300167630ustar00rootroot00000000000000echo "List of Acorn contributors. Updated before every release." > AUTHORS echo >> AUTHORS git log --format='%aN' | grep -v 'Adrian Heine né Lang' | grep -v abraidwood | grep -v Rich-Harris | grep -v ForbesLindesay | sort -u >> AUTHORS acorn-5.5.3/package.json000066400000000000000000000032661325020065300151170ustar00rootroot00000000000000{ "name": "acorn", "description": "ECMAScript parser", "homepage": "https://github.com/acornjs/acorn", "main": "dist/acorn.js", "module": "dist/acorn.es.js", "version": "5.5.3", "engines": { "node": ">=0.4.0" }, "maintainers": [ { "name": "Marijn Haverbeke", "email": "marijnh@gmail.com", "web": "http://marijnhaverbeke.nl" }, { "name": "Ingvar Stepanyan", "email": "me@rreverser.com", "web": "http://rreverser.com/" } ], "repository": { "type": "git", "url": "https://github.com/acornjs/acorn.git" }, "license": "MIT", "scripts": { "prepare": "npm test", "test": "node test/run.js && node test/lint.js", "pretest": "npm run build:main && npm run build:loose", "test:test262": "node bin/run_test262.js", "build": "npm run build:main && npm run build:walk && npm run build:loose && npm run build:bin", "build:main": "rollup -c rollup/config.main.js", "build:walk": "rollup -c rollup/config.walk.js", "build:loose": "rollup -c rollup/config.loose.js && rollup -c rollup/config.loose_es.js", "build:bin": "rollup -c rollup/config.bin.js", "lint": "eslint src/" }, "bin": { "acorn": "./bin/acorn" }, "devDependencies": { "eslint": "^4.10.0", "eslint-config-standard": "^10.2.1", "eslint-plugin-import": "^2.2.0", "eslint-plugin-node": "^5.2.1", "eslint-plugin-promise": "^3.5.0", "eslint-plugin-standard": "^3.0.1", "rollup": "^0.45.0", "rollup-plugin-buble": "^0.16.0", "test262": "git+https://github.com/tc39/test262.git#18c1e799a01cc976695983b61e225ce7959bdd91", "test262-parser-runner": "^0.3.1", "unicode-10.0.0": "^0.7.5" } } acorn-5.5.3/rollup/000077500000000000000000000000001325020065300141375ustar00rootroot00000000000000acorn-5.5.3/rollup/config.bin.js000066400000000000000000000004261325020065300165130ustar00rootroot00000000000000import buble from 'rollup-plugin-buble' export default { entry: 'src/bin/acorn.js', dest: 'bin/_acorn.js', format: 'cjs', banner: '#!/usr/bin/env node', external: [ 'fs', 'path', 'acorn' ], paths: { acorn: '../dist/acorn.js' }, plugins: [ buble() ] } acorn-5.5.3/rollup/config.loose.js000066400000000000000000000007371325020065300170710ustar00rootroot00000000000000import buble from 'rollup-plugin-buble' import {resolve} from 'path' var acorn = resolve('src/index.js') var paths = {}, globals = {} paths[acorn] = './acorn' globals[acorn] = 'acorn' export default { entry: 'src/loose/index.js', moduleName: 'acorn.loose', external: [ acorn ], paths: paths, globals: globals, targets: [ { dest: 'dist/acorn_loose.js', format: 'umd' } ], plugins: [ buble({ transforms: { dangerousForOf: true } }) ] } acorn-5.5.3/rollup/config.loose_es.js000066400000000000000000000007441325020065300175560ustar00rootroot00000000000000import buble from 'rollup-plugin-buble' import {resolve} from 'path' var acorn = resolve('src/index.js') var paths = {}, globals = {} paths[acorn] = './acorn.es' globals[acorn] = 'acorn' export default { entry: 'src/loose/index.js', moduleName: 'acorn.loose', external: [ acorn ], paths: paths, globals: globals, targets: [ { dest: 'dist/acorn_loose.es.js', format: 'es' } ], plugins: [ buble({ transforms: { dangerousForOf: true } }) ] } acorn-5.5.3/rollup/config.main.js000066400000000000000000000004421325020065300166650ustar00rootroot00000000000000import buble from 'rollup-plugin-buble'; export default { entry: 'src/index.js', moduleName: 'acorn', plugins: [ buble({ transforms: { dangerousForOf: true } }) ], targets: [ { dest: 'dist/acorn.js', format: 'umd' }, { dest: 'dist/acorn.es.js', format: 'es' } ] }; acorn-5.5.3/rollup/config.walk.js000066400000000000000000000004521325020065300167000ustar00rootroot00000000000000import buble from 'rollup-plugin-buble'; export default { entry: 'src/walk/index.js', moduleName: 'acorn.walk', plugins: [ buble({ transforms: { dangerousForOf: true } }) ], targets: [ { dest: 'dist/walk.js', format: 'umd' }, { dest: 'dist/walk.es.js', format: 'es' } ] }; acorn-5.5.3/src/000077500000000000000000000000001325020065300134115ustar00rootroot00000000000000acorn-5.5.3/src/.eslintrc000066400000000000000000000016361325020065300152430ustar00rootroot00000000000000{ "extends": [ "eslint:recommended", "standard", "plugin:import/errors", "plugin:import/warnings" ], "rules": { "curly": "off", "eqeqeq": "off", "indent": ["error", 2, { "SwitchCase": 0, "VariableDeclarator": 2, "CallExpression": { arguments: "off" } }], "new-parens": "off", "no-case-declarations": "off", "no-cond-assign": "off", "no-fallthrough": "off", "no-labels": "off", "no-mixed-operators": "off", "no-return-assign": "off", "no-unused-labels": "error", "no-var": "error", "object-curly-spacing": ["error", "never"], "one-var": "off", "quotes": ["error", "double"], "semi-spacing": "off", "space-before-function-paren": ["error", "never"] }, "globals": { "Packages": false }, "plugins": [ "import" ] } acorn-5.5.3/src/bin/000077500000000000000000000000001325020065300141615ustar00rootroot00000000000000acorn-5.5.3/src/bin/.eslintrc000066400000000000000000000001231325020065300160010ustar00rootroot00000000000000{ "extends": "../.eslintrc", "rules": { "no-console": "off" } }acorn-5.5.3/src/bin/acorn.js000066400000000000000000000037501325020065300156260ustar00rootroot00000000000000import {basename} from "path" import {readFileSync as readFile} from "fs" import * as acorn from "acorn" let infile, forceFile, silent = false, compact = false, tokenize = false const options = {} function help(status) { const print = (status == 0) ? console.log : console.error print("usage: " + basename(process.argv[1]) + " [--ecma3|--ecma5|--ecma6|--ecma7|--ecma8|--ecma9|...|--ecma2015|--ecma2016|--ecma2017|--ecma2018|...]") print(" [--tokenize] [--locations] [---allow-hash-bang] [--compact] [--silent] [--module] [--help] [--] [infile]") process.exit(status) } for (let i = 2; i < process.argv.length; ++i) { const arg = process.argv[i] if ((arg == "-" || arg[0] != "-") && !infile) infile = arg else if (arg == "--" && !infile && i + 2 == process.argv.length) forceFile = infile = process.argv[++i] else if (arg == "--locations") options.locations = true else if (arg == "--allow-hash-bang") options.allowHashBang = 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 if (arg == "--module") options.sourceType = "module" else { let match = arg.match(/^--ecma(\d+)$/) if (match) options.ecmaVersion = +match[1] else help(1) } } function run(code) { let result try { if (!tokenize) { result = acorn.parse(code, options) } else { result = [] let tokenizer = acorn.tokenizer(code, options), token do { token = tokenizer.getToken() result.push(token) } while (token.type != acorn.tokTypes.eof) } } catch (e) { console.error(e.message) process.exit(1) } if (!silent) console.log(JSON.stringify(result, null, compact ? null : 2)) } if (forceFile || infile && infile != "-") { run(readFile(infile, "utf8")) } else { let code = "" process.stdin.resume() process.stdin.on("data", chunk => code += chunk) process.stdin.on("end", () => run(code)) } acorn-5.5.3/src/expression.js000066400000000000000000001031441325020065300161510ustar00rootroot00000000000000// A recursive descent parser operates by defining functions for all // syntactic elements, and recursively calling those, each function // advancing the input stream and returning an AST node. Precedence // of constructs (for example, the fact that `!x[1]` means `!(x[1])` // instead of `(!x)[1]` is handled by the fact that the parser // function that parses unary prefix operators is called first, and // in turn calls the function that parses `[]` subscripts — that // way, it'll receive the node for `x[1]` already parsed, and wraps // *that* in the unary operator node. // // Acorn uses an [operator precedence parser][opp] to handle binary // operator precedence, because it is much more compact than using // the technique outlined above, which uses different, nesting // functions to specify precedence, for all of the ten binary // precedence levels that JavaScript defines. // // [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser import {types as tt} from "./tokentype" import {Parser} from "./state" import {DestructuringErrors} from "./parseutil" import {lineBreak} from "./whitespace" const pp = Parser.prototype // Check if property name clashes with already added. // Object/class getters and setters are not allowed to clash — // either with each other or with an init property — and in // strict mode, init properties are also not allowed to be repeated. pp.checkPropClash = function(prop, propHash, refDestructuringErrors) { if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement") return if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) return let {key} = prop, name switch (key.type) { case "Identifier": name = key.name; break case "Literal": name = String(key.value); break default: return } let {kind} = prop if (this.options.ecmaVersion >= 6) { if (name === "__proto__" && kind === "init") { if (propHash.proto) { if (refDestructuringErrors && refDestructuringErrors.doubleProto < 0) refDestructuringErrors.doubleProto = key.start // Backwards-compat kludge. Can be removed in version 6.0 else this.raiseRecoverable(key.start, "Redefinition of __proto__ property") } propHash.proto = true } return } name = "$" + name let other = propHash[name] if (other) { let redefinition if (kind === "init") { redefinition = this.strict && other.init || other.get || other.set } else { redefinition = other.init || other[kind] } if (redefinition) this.raiseRecoverable(key.start, "Redefinition of property") } else { other = propHash[name] = { init: false, get: false, set: false } } other[kind] = true } // ### Expression parsing // These nest, from the most general expression type at the top to // 'atomic', nondivisible expression types at the bottom. Most of // the functions will simply let the function(s) below them parse, // and, *if* the syntactic construct they handle is present, wrap // the AST node that the inner parser gave them in another node. // Parse a full expression. The optional arguments are used to // forbid the `in` operator (in for loops initalization expressions) // and provide reference for storing '=' operator inside shorthand // property assignment in contexts where both object expression // and object pattern might appear (so it's possible to raise // delayed syntax error at correct position). pp.parseExpression = function(noIn, refDestructuringErrors) { let startPos = this.start, startLoc = this.startLoc let expr = this.parseMaybeAssign(noIn, refDestructuringErrors) if (this.type === tt.comma) { let node = this.startNodeAt(startPos, startLoc) node.expressions = [expr] while (this.eat(tt.comma)) node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors)) return this.finishNode(node, "SequenceExpression") } return expr } // Parse an assignment expression. This includes applications of // operators like `+=`. pp.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { if (this.inGenerator && this.isContextual("yield")) return this.parseYield() let ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1 if (refDestructuringErrors) { oldParenAssign = refDestructuringErrors.parenthesizedAssign oldTrailingComma = refDestructuringErrors.trailingComma refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1 } else { refDestructuringErrors = new DestructuringErrors ownDestructuringErrors = true } let startPos = this.start, startLoc = this.startLoc if (this.type == tt.parenL || this.type == tt.name) this.potentialArrowAt = this.start let left = this.parseMaybeConditional(noIn, refDestructuringErrors) if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc) if (this.type.isAssign) { let node = this.startNodeAt(startPos, startLoc) node.operator = this.value node.left = this.type === tt.eq ? this.toAssignable(left, false, refDestructuringErrors) : left if (!ownDestructuringErrors) DestructuringErrors.call(refDestructuringErrors) refDestructuringErrors.shorthandAssign = -1 // reset because shorthand default was used correctly this.checkLVal(left) this.next() node.right = this.parseMaybeAssign(noIn) return this.finishNode(node, "AssignmentExpression") } else { if (ownDestructuringErrors) this.checkExpressionErrors(refDestructuringErrors, true) } if (oldParenAssign > -1) refDestructuringErrors.parenthesizedAssign = oldParenAssign if (oldTrailingComma > -1) refDestructuringErrors.trailingComma = oldTrailingComma return left } // Parse a ternary conditional (`?:`) operator. pp.parseMaybeConditional = function(noIn, refDestructuringErrors) { let startPos = this.start, startLoc = this.startLoc let expr = this.parseExprOps(noIn, refDestructuringErrors) if (this.checkExpressionErrors(refDestructuringErrors)) return expr if (this.eat(tt.question)) { let node = this.startNodeAt(startPos, startLoc) node.test = expr node.consequent = this.parseMaybeAssign() this.expect(tt.colon) node.alternate = this.parseMaybeAssign(noIn) return this.finishNode(node, "ConditionalExpression") } return expr } // Start the precedence parser. pp.parseExprOps = function(noIn, refDestructuringErrors) { let startPos = this.start, startLoc = this.startLoc let expr = this.parseMaybeUnary(refDestructuringErrors, false) if (this.checkExpressionErrors(refDestructuringErrors)) return expr return expr.start == startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn) } // Parse binary operators with the operator precedence parsing // algorithm. `left` is the left-hand side of the operator. // `minPrec` provides context that allows the function to stop and // defer further parser to one of its callers when it encounters an // operator that has a lower precedence than the set it is parsing. pp.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) { let prec = this.type.binop if (prec != null && (!noIn || this.type !== tt._in)) { if (prec > minPrec) { let logical = this.type === tt.logicalOR || this.type === tt.logicalAND let op = this.value this.next() let startPos = this.start, startLoc = this.startLoc let right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn) let node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical) return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn) } } return left } pp.buildBinary = function(startPos, startLoc, left, right, op, logical) { let node = this.startNodeAt(startPos, startLoc) node.left = left node.operator = op node.right = right return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression") } // Parse unary operators, both prefix and postfix. pp.parseMaybeUnary = function(refDestructuringErrors, sawUnary) { let startPos = this.start, startLoc = this.startLoc, expr if (this.inAsync && this.isContextual("await")) { expr = this.parseAwait() sawUnary = true } else if (this.type.prefix) { let node = this.startNode(), update = this.type === tt.incDec node.operator = this.value node.prefix = true this.next() node.argument = this.parseMaybeUnary(null, true) this.checkExpressionErrors(refDestructuringErrors, true) if (update) this.checkLVal(node.argument) else if (this.strict && node.operator === "delete" && node.argument.type === "Identifier") this.raiseRecoverable(node.start, "Deleting local variable in strict mode") else sawUnary = true expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression") } else { expr = this.parseExprSubscripts(refDestructuringErrors) if (this.checkExpressionErrors(refDestructuringErrors)) return expr while (this.type.postfix && !this.canInsertSemicolon()) { let node = this.startNodeAt(startPos, startLoc) node.operator = this.value node.prefix = false node.argument = expr this.checkLVal(expr) this.next() expr = this.finishNode(node, "UpdateExpression") } } if (!sawUnary && this.eat(tt.starstar)) return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) else return expr } // Parse call, dot, and `[]`-subscript expressions. pp.parseExprSubscripts = function(refDestructuringErrors) { let startPos = this.start, startLoc = this.startLoc let expr = this.parseExprAtom(refDestructuringErrors) let skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")" if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) return expr let result = this.parseSubscripts(expr, startPos, startLoc) if (refDestructuringErrors && result.type === "MemberExpression") { if (refDestructuringErrors.parenthesizedAssign >= result.start) refDestructuringErrors.parenthesizedAssign = -1 if (refDestructuringErrors.parenthesizedBind >= result.start) refDestructuringErrors.parenthesizedBind = -1 } return result } pp.parseSubscripts = function(base, startPos, startLoc, noCalls) { let maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && this.lastTokEnd == base.end && !this.canInsertSemicolon() && this.input.slice(base.start, base.end) === "async" for (let computed;;) { if ((computed = this.eat(tt.bracketL)) || this.eat(tt.dot)) { let node = this.startNodeAt(startPos, startLoc) node.object = base node.property = computed ? this.parseExpression() : this.parseIdent(true) node.computed = !!computed if (computed) this.expect(tt.bracketR) base = this.finishNode(node, "MemberExpression") } else if (!noCalls && this.eat(tt.parenL)) { let refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos this.yieldPos = 0 this.awaitPos = 0 let exprList = this.parseExprList(tt.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors) if (maybeAsyncArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) { this.checkPatternErrors(refDestructuringErrors, false) this.checkYieldAwaitInDefaultParams() this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true) } this.checkExpressionErrors(refDestructuringErrors, true) this.yieldPos = oldYieldPos || this.yieldPos this.awaitPos = oldAwaitPos || this.awaitPos let node = this.startNodeAt(startPos, startLoc) node.callee = base node.arguments = exprList base = this.finishNode(node, "CallExpression") } else if (this.type === tt.backQuote) { let node = this.startNodeAt(startPos, startLoc) node.tag = base node.quasi = this.parseTemplate({isTagged: true}) base = this.finishNode(node, "TaggedTemplateExpression") } else { return base } } } // Parse an atomic expression — either a single token that is an // expression, an expression started by a keyword like `function` or // `new`, or an expression wrapped in punctuation like `()`, `[]`, // or `{}`. pp.parseExprAtom = function(refDestructuringErrors) { let node, canBeArrow = this.potentialArrowAt == this.start switch (this.type) { case tt._super: if (!this.inFunction) this.raise(this.start, "'super' outside of function or class") node = this.startNode() this.next() // The `super` keyword can appear at below: // SuperProperty: // super [ Expression ] // super . IdentifierName // SuperCall: // super Arguments if (this.type !== tt.dot && this.type !== tt.bracketL && this.type !== tt.parenL) this.unexpected() return this.finishNode(node, "Super") case tt._this: node = this.startNode() this.next() return this.finishNode(node, "ThisExpression") case tt.name: let startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc let id = this.parseIdent(this.type !== tt.name) if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(tt._function)) return this.parseFunction(this.startNodeAt(startPos, startLoc), false, false, true) if (canBeArrow && !this.canInsertSemicolon()) { if (this.eat(tt.arrow)) return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === tt.name && !containsEsc) { id = this.parseIdent() if (this.canInsertSemicolon() || !this.eat(tt.arrow)) this.unexpected() return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true) } } return id case tt.regexp: let value = this.value node = this.parseLiteral(value.value) node.regex = {pattern: value.pattern, flags: value.flags} return node case tt.num: case tt.string: return this.parseLiteral(this.value) case tt._null: case tt._true: case tt._false: node = this.startNode() node.value = this.type === tt._null ? null : this.type === tt._true node.raw = this.type.keyword this.next() return this.finishNode(node, "Literal") case tt.parenL: let start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow) if (refDestructuringErrors) { if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) refDestructuringErrors.parenthesizedAssign = start if (refDestructuringErrors.parenthesizedBind < 0) refDestructuringErrors.parenthesizedBind = start } return expr case tt.bracketL: node = this.startNode() this.next() node.elements = this.parseExprList(tt.bracketR, true, true, refDestructuringErrors) return this.finishNode(node, "ArrayExpression") case tt.braceL: return this.parseObj(false, refDestructuringErrors) case tt._function: node = this.startNode() this.next() return this.parseFunction(node, false) case tt._class: return this.parseClass(this.startNode(), false) case tt._new: return this.parseNew() case tt.backQuote: return this.parseTemplate() default: this.unexpected() } } pp.parseLiteral = function(value) { let node = this.startNode() node.value = value node.raw = this.input.slice(this.start, this.end) this.next() return this.finishNode(node, "Literal") } pp.parseParenExpression = function() { this.expect(tt.parenL) let val = this.parseExpression() this.expect(tt.parenR) return val } pp.parseParenAndDistinguishExpression = function(canBeArrow) { let startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8 if (this.options.ecmaVersion >= 6) { this.next() let innerStartPos = this.start, innerStartLoc = this.startLoc let exprList = [], first = true, lastIsComma = false let refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart this.yieldPos = 0 this.awaitPos = 0 while (this.type !== tt.parenR) { first ? first = false : this.expect(tt.comma) if (allowTrailingComma && this.afterTrailingComma(tt.parenR, true)) { lastIsComma = true break } else if (this.type === tt.ellipsis) { spreadStart = this.start exprList.push(this.parseParenItem(this.parseRestBinding())) if (this.type === tt.comma) this.raise(this.start, "Comma is not permitted after the rest element") break } else { exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)) } } let innerEndPos = this.start, innerEndLoc = this.startLoc this.expect(tt.parenR) if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) { this.checkPatternErrors(refDestructuringErrors, false) this.checkYieldAwaitInDefaultParams() this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos return this.parseParenArrowList(startPos, startLoc, exprList) } if (!exprList.length || lastIsComma) this.unexpected(this.lastTokStart) if (spreadStart) this.unexpected(spreadStart) this.checkExpressionErrors(refDestructuringErrors, true) this.yieldPos = oldYieldPos || this.yieldPos this.awaitPos = oldAwaitPos || this.awaitPos if (exprList.length > 1) { val = this.startNodeAt(innerStartPos, innerStartLoc) val.expressions = exprList this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc) } else { val = exprList[0] } } else { val = this.parseParenExpression() } if (this.options.preserveParens) { let par = this.startNodeAt(startPos, startLoc) par.expression = val return this.finishNode(par, "ParenthesizedExpression") } else { return val } } pp.parseParenItem = function(item) { return item } pp.parseParenArrowList = function(startPos, startLoc, exprList) { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList) } // 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 noCalls // argument to parseSubscripts to prevent it from consuming the // argument list. const empty = [] pp.parseNew = function() { let node = this.startNode() let meta = this.parseIdent(true) if (this.options.ecmaVersion >= 6 && this.eat(tt.dot)) { node.meta = meta let containsEsc = this.containsEsc node.property = this.parseIdent(true) if (node.property.name !== "target" || containsEsc) this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target") if (!this.inFunction) this.raiseRecoverable(node.start, "new.target can only be used in functions") return this.finishNode(node, "MetaProperty") } let startPos = this.start, startLoc = this.startLoc node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true) if (this.eat(tt.parenL)) node.arguments = this.parseExprList(tt.parenR, this.options.ecmaVersion >= 8, false) else node.arguments = empty return this.finishNode(node, "NewExpression") } // Parse template expression. pp.parseTemplateElement = function({isTagged}) { let elem = this.startNode() if (this.type === tt.invalidTemplate) { if (!isTagged) { this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal") } elem.value = { raw: this.value, cooked: null } } else { elem.value = { raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), cooked: this.value } } this.next() elem.tail = this.type === tt.backQuote return this.finishNode(elem, "TemplateElement") } pp.parseTemplate = function({isTagged = false} = {}) { let node = this.startNode() this.next() node.expressions = [] let curElt = this.parseTemplateElement({isTagged}) node.quasis = [curElt] while (!curElt.tail) { this.expect(tt.dollarBraceL) node.expressions.push(this.parseExpression()) this.expect(tt.braceR) node.quasis.push(curElt = this.parseTemplateElement({isTagged})) } this.next() return this.finishNode(node, "TemplateLiteral") } pp.isAsyncProp = function(prop) { return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && (this.type === tt.name || this.type === tt.num || this.type === tt.string || this.type === tt.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === tt.star)) && !lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } // Parse an object literal or binding pattern. pp.parseObj = function(isPattern, refDestructuringErrors) { let node = this.startNode(), first = true, propHash = {} node.properties = [] this.next() while (!this.eat(tt.braceR)) { if (!first) { this.expect(tt.comma) if (this.afterTrailingComma(tt.braceR)) break } else first = false const prop = this.parseProperty(isPattern, refDestructuringErrors) if (!isPattern) this.checkPropClash(prop, propHash, refDestructuringErrors) node.properties.push(prop) } return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") } pp.parseProperty = function(isPattern, refDestructuringErrors) { let prop = this.startNode(), isGenerator, isAsync, startPos, startLoc if (this.options.ecmaVersion >= 9 && this.eat(tt.ellipsis)) { if (isPattern) { prop.argument = this.parseIdent(false) if (this.type === tt.comma) { this.raise(this.start, "Comma is not permitted after the rest element") } return this.finishNode(prop, "RestElement") } // To disallow parenthesized identifier via `this.toAssignable()`. if (this.type === tt.parenL && refDestructuringErrors) { if (refDestructuringErrors.parenthesizedAssign < 0) { refDestructuringErrors.parenthesizedAssign = this.start } if (refDestructuringErrors.parenthesizedBind < 0) { refDestructuringErrors.parenthesizedBind = this.start } } // Parse argument. prop.argument = this.parseMaybeAssign(false, refDestructuringErrors) // To disallow trailing comma via `this.toAssignable()`. if (this.type === tt.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) { refDestructuringErrors.trailingComma = this.start } // Finish return this.finishNode(prop, "SpreadElement") } if (this.options.ecmaVersion >= 6) { prop.method = false prop.shorthand = false if (isPattern || refDestructuringErrors) { startPos = this.start startLoc = this.startLoc } if (!isPattern) isGenerator = this.eat(tt.star) } let containsEsc = this.containsEsc this.parsePropertyName(prop) if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) { isAsync = true isGenerator = this.options.ecmaVersion >= 9 && this.eat(tt.star) this.parsePropertyName(prop, refDestructuringErrors) } else { isAsync = false } this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) return this.finishNode(prop, "Property") } pp.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) { if ((isGenerator || isAsync) && this.type === tt.colon) this.unexpected() if (this.eat(tt.colon)) { prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors) prop.kind = "init" } else if (this.options.ecmaVersion >= 6 && this.type === tt.parenL) { if (isPattern) this.unexpected() prop.kind = "init" prop.method = true prop.value = this.parseMethod(isGenerator, isAsync) } else if (!isPattern && !containsEsc && this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set") && (this.type != tt.comma && this.type != tt.braceR)) { if (isGenerator || isAsync) this.unexpected() prop.kind = prop.key.name this.parsePropertyName(prop) prop.value = this.parseMethod(false) let paramCount = prop.kind === "get" ? 0 : 1 if (prop.value.params.length !== paramCount) { let start = prop.value.start if (prop.kind === "get") this.raiseRecoverable(start, "getter should have no params") else this.raiseRecoverable(start, "setter should have exactly one param") } else { if (prop.kind === "set" && prop.value.params[0].type === "RestElement") this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params") } } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { this.checkUnreserved(prop.key) prop.kind = "init" if (isPattern) { prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key) } else if (this.type === tt.eq && refDestructuringErrors) { if (refDestructuringErrors.shorthandAssign < 0) refDestructuringErrors.shorthandAssign = this.start prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key) } else { prop.value = prop.key } prop.shorthand = true } else this.unexpected() } pp.parsePropertyName = function(prop) { if (this.options.ecmaVersion >= 6) { if (this.eat(tt.bracketL)) { prop.computed = true prop.key = this.parseMaybeAssign() this.expect(tt.bracketR) return prop.key } else { prop.computed = false } } return prop.key = this.type === tt.num || this.type === tt.string ? this.parseExprAtom() : this.parseIdent(true) } // Initialize empty function node. pp.initFunction = function(node) { node.id = null if (this.options.ecmaVersion >= 6) { node.generator = false node.expression = false } if (this.options.ecmaVersion >= 8) node.async = false } // Parse object or class method. pp.parseMethod = function(isGenerator, isAsync) { let node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction this.initFunction(node) if (this.options.ecmaVersion >= 6) node.generator = isGenerator if (this.options.ecmaVersion >= 8) node.async = !!isAsync this.inGenerator = node.generator this.inAsync = node.async this.yieldPos = 0 this.awaitPos = 0 this.inFunction = true this.enterFunctionScope() this.expect(tt.parenL) node.params = this.parseBindingList(tt.parenR, false, this.options.ecmaVersion >= 8) this.checkYieldAwaitInDefaultParams() this.parseFunctionBody(node, false) this.inGenerator = oldInGen this.inAsync = oldInAsync this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos this.inFunction = oldInFunc return this.finishNode(node, "FunctionExpression") } // Parse arrow function expression with given parameters. pp.parseArrowExpression = function(node, params, isAsync) { let oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction this.enterFunctionScope() this.initFunction(node) if (this.options.ecmaVersion >= 8) node.async = !!isAsync this.inGenerator = false this.inAsync = node.async this.yieldPos = 0 this.awaitPos = 0 this.inFunction = true node.params = this.toAssignableList(params, true) this.parseFunctionBody(node, true) this.inGenerator = oldInGen this.inAsync = oldInAsync this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos this.inFunction = oldInFunc return this.finishNode(node, "ArrowFunctionExpression") } // Parse function body and check parameters. pp.parseFunctionBody = function(node, isArrowFunction) { let isExpression = isArrowFunction && this.type !== tt.braceL let oldStrict = this.strict, useStrict = false if (isExpression) { node.body = this.parseMaybeAssign() node.expression = true this.checkParams(node, false) } else { let nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params) if (!oldStrict || nonSimple) { useStrict = this.strictDirective(this.end) // If this is a strict mode function, verify that argument names // are not repeated, and it does not try to bind the words `eval` // or `arguments`. if (useStrict && nonSimple) this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list") } // Start a new scope with regard to labels and the `inFunction` // flag (restore them to their old value afterwards). let oldLabels = this.labels this.labels = [] if (useStrict) this.strict = true // Add the params to varDeclaredNames to ensure that an error is thrown // if a let/const declaration in the function clashes with one of the params. this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params)) node.body = this.parseBlock(false) node.expression = false this.adaptDirectivePrologue(node.body.body) this.labels = oldLabels } this.exitFunctionScope() if (this.strict && node.id) { // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' this.checkLVal(node.id, "none") } this.strict = oldStrict } pp.isSimpleParamList = function(params) { for (let param of params) if (param.type !== "Identifier") return false return true } // Checks function params for various disallowed patterns such as using "eval" // or "arguments" and duplicate parameters. pp.checkParams = function(node, allowDuplicates) { let nameHash = {} for (let param of node.params) this.checkLVal(param, "var", allowDuplicates ? null : nameHash) } // 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 // nothing in between them to be parsed as `null` (which is needed // for array literals). pp.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { let elts = [], first = true while (!this.eat(close)) { if (!first) { this.expect(tt.comma) if (allowTrailingComma && this.afterTrailingComma(close)) break } else first = false let elt if (allowEmpty && this.type === tt.comma) elt = null else if (this.type === tt.ellipsis) { elt = this.parseSpread(refDestructuringErrors) if (refDestructuringErrors && this.type === tt.comma && refDestructuringErrors.trailingComma < 0) refDestructuringErrors.trailingComma = this.start } else { elt = this.parseMaybeAssign(false, refDestructuringErrors) } elts.push(elt) } return elts } pp.checkUnreserved = function({start, end, name}) { if (this.inGenerator && name === "yield") this.raiseRecoverable(start, "Can not use 'yield' as identifier inside a generator") if (this.inAsync && name === "await") this.raiseRecoverable(start, "Can not use 'await' as identifier inside an async function") if (this.isKeyword(name)) this.raise(start, `Unexpected keyword '${name}'`) if (this.options.ecmaVersion < 6 && this.input.slice(start, end).indexOf("\\") != -1) return const re = this.strict ? this.reservedWordsStrict : this.reservedWords if (re.test(name)) { if (!this.inAsync && name === "await") this.raiseRecoverable(start, "Can not use keyword 'await' outside an async function") this.raiseRecoverable(start, `The keyword '${name}' is reserved`) } } // Parse the next token as an identifier. If `liberal` is true (used // when parsing properties), it will also convert keywords into // identifiers. pp.parseIdent = function(liberal, isBinding) { let node = this.startNode() if (liberal && this.options.allowReserved == "never") liberal = false if (this.type === tt.name) { node.name = this.value } else if (this.type.keyword) { node.name = this.type.keyword // To fix https://github.com/acornjs/acorn/issues/575 // `class` and `function` keywords push new context into this.context. // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name. // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword if ((node.name === "class" || node.name === "function") && (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { this.context.pop() } } else { this.unexpected() } this.next() this.finishNode(node, "Identifier") if (!liberal) this.checkUnreserved(node) return node } // Parses yield expression inside generator. pp.parseYield = function() { if (!this.yieldPos) this.yieldPos = this.start let node = this.startNode() this.next() if (this.type == tt.semi || this.canInsertSemicolon() || (this.type != tt.star && !this.type.startsExpr)) { node.delegate = false node.argument = null } else { node.delegate = this.eat(tt.star) node.argument = this.parseMaybeAssign() } return this.finishNode(node, "YieldExpression") } pp.parseAwait = function() { if (!this.awaitPos) this.awaitPos = this.start let node = this.startNode() this.next() node.argument = this.parseMaybeUnary(null, true) return this.finishNode(node, "AwaitExpression") } acorn-5.5.3/src/identifier.js000066400000000000000000000270551325020065300161020ustar00rootroot00000000000000// Reserved word lists for various dialects of the language export const reservedWords = { 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", 5: "class enum extends super const export import", 6: "enum", strict: "implements interface let package private protected public static yield", strictBind: "eval arguments" } // And the keywords const ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this" export const keywords = { 5: ecma5AndLessKeywords, 6: ecma5AndLessKeywords + " const class extends export import super" } export const keywordRelationalOperator = /^in(stanceof)?$/ // ## Character categories // Big ugly regular expressions that match characters in the // whitespace, identifier, and identifier-start categories. These // are only applied when a character is found to actually have a // code point above 128. // Generated by `bin/generate-identifier-regex.js`. let nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312e\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fea\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ae\ua7b0-\ua7b7\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab65\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc" let nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d4-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f" const nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]") const nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]") nonASCIIidentifierStartChars = nonASCIIidentifierChars = null // These are a run-length and offset encoded representation of the // >0xffff code points that are a valid part of identifiers. The // offset starts at 0x10000, and each pair of numbers represents an // offset to the next range, and then a size of the range. They were // generated by bin/generate-identifier-regex.js // eslint-disable-next-line comma-spacing const astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,26,45,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,785,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,25,391,63,32,0,257,0,11,39,8,0,22,0,12,39,3,3,55,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,698,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,65,1,31,6124,20,754,9486,286,82,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,60,67,1213,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,15,7472,3104,541] // eslint-disable-next-line comma-spacing const astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,1306,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,52,0,13,2,49,13,10,2,4,9,83,11,7,0,161,11,6,9,7,3,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,87,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,423,9,280,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,19719,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239] // This has a complexity linear to the value of the code. The // assumption is that looking up astral identifier characters is // rare. function isInAstralSet(code, set) { let pos = 0x10000 for (let i = 0; i < set.length; i += 2) { pos += set[i] if (pos > code) return false pos += set[i + 1] if (pos >= code) return true } } // Test whether a given character code starts an identifier. export function isIdentifierStart(code, astral) { if (code < 65) return code === 36 if (code < 91) return true if (code < 97) return code === 95 if (code < 123) return true if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) if (astral === false) return false return isInAstralSet(code, astralIdentifierStartCodes) } // Test whether a given character is part of an identifier. export function isIdentifierChar(code, astral) { if (code < 48) return code === 36 if (code < 58) return true if (code < 65) return false if (code < 91) return true if (code < 97) return code === 95 if (code < 123) return true if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) if (astral === false) return false return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) } acorn-5.5.3/src/index.js000066400000000000000000000051721325020065300150630ustar00rootroot00000000000000// Acorn is a tiny, fast JavaScript parser written in JavaScript. // // Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and // various contributors and released under an MIT license. // // Git repositories for Acorn are available at // // http://marijnhaverbeke.nl/git/acorn // https://github.com/acornjs/acorn.git // // Please use the [github bug tracker][ghbt] to report issues. // // [ghbt]: https://github.com/acornjs/acorn/issues // // This file defines the main parser interface. The library also comes // with a [error-tolerant parser][dammit] and an // [abstract syntax tree walker][walk], defined in other files. // // [dammit]: acorn_loose.js // [walk]: util/walk.js import {Parser} from "./state" import "./parseutil" import "./statement" import "./lval" import "./expression" import "./location" import "./scope" export {Parser, plugins} from "./state" export {defaultOptions} from "./options" export {Position, SourceLocation, getLineInfo} from "./locutil" export {Node} from "./node" export {TokenType, types as tokTypes, keywords as keywordTypes} from "./tokentype" export {TokContext, types as tokContexts} from "./tokencontext" export {isIdentifierChar, isIdentifierStart} from "./identifier" export {Token} from "./tokenize" export {isNewLine, lineBreak, lineBreakG, nonASCIIwhitespace} from "./whitespace" export const version = "5.5.3" // The main exported interface (under `self.acorn` when in the // browser) is a `parse` function that takes a code string and // returns an abstract syntax tree as specified by [Mozilla parser // API][api]. // // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API export function parse(input, options) { return new Parser(options, input).parse() } // This function tries to parse a single expression at a given // offset in a string. Useful for parsing mixed-language formats // that embed JavaScript expressions. export function parseExpressionAt(input, pos, options) { let p = new Parser(options, input, pos) p.nextToken() return p.parseExpression() } // Acorn is organized as a tokenizer and a recursive-descent parser. // The `tokenizer` export provides an interface to the tokenizer. export function tokenizer(input, options) { return new Parser(options, input) } // This is a terrible kludge to support the existing, pre-ES6 // interface where the loose parser module retroactively adds exports // to this module. export let parse_dammit, LooseParser, pluginsLoose // eslint-disable-line camelcase export function addLooseExports(parse, Parser, plugins) { parse_dammit = parse // eslint-disable-line camelcase LooseParser = Parser pluginsLoose = plugins } acorn-5.5.3/src/location.js000066400000000000000000000014231325020065300155570ustar00rootroot00000000000000import {Parser} from "./state" import {Position, getLineInfo} from "./locutil" const pp = Parser.prototype // This function is used to raise exceptions on parse errors. It // takes an offset integer (into the current `input`) to indicate // the location of the error, attaches the position to the end // of the error message, and then raises a `SyntaxError` with that // message. pp.raise = function(pos, message) { let loc = getLineInfo(this.input, pos) message += " (" + loc.line + ":" + loc.column + ")" let err = new SyntaxError(message) err.pos = pos; err.loc = loc; err.raisedAt = this.pos throw err } pp.raiseRecoverable = pp.raise pp.curPosition = function() { if (this.options.locations) { return new Position(this.curLine, this.pos - this.lineStart) } } acorn-5.5.3/src/locutil.js000066400000000000000000000020371325020065300154240ustar00rootroot00000000000000import {lineBreakG} from "./whitespace" // These are used when `options.locations` is on, for the // `startLoc` and `endLoc` properties. export class Position { constructor(line, col) { this.line = line this.column = col } offset(n) { return new Position(this.line, this.column + n) } } export class SourceLocation { constructor(p, start, end) { this.start = start this.end = end if (p.sourceFile !== null) this.source = p.sourceFile } } // The `getLineInfo` function is mostly useful when the // `locations` option is off (for performance reasons) and you // want to find the line/column position for a given character // offset. `input` should be the code string that the offset refers // into. export function getLineInfo(input, offset) { for (let line = 1, cur = 0;;) { lineBreakG.lastIndex = cur let match = lineBreakG.exec(input) if (match && match.index < offset) { ++line cur = match.index + match[0].length } else { return new Position(line, offset - cur) } } } acorn-5.5.3/src/loose/000077500000000000000000000000001325020065300145325ustar00rootroot00000000000000acorn-5.5.3/src/loose/expression.js000066400000000000000000000440331325020065300172730ustar00rootroot00000000000000import {LooseParser} from "./state" import {isDummy} from "./parseutil" import {tokTypes as tt} from "../index" const lp = LooseParser.prototype lp.checkLVal = function(expr) { if (!expr) return expr switch (expr.type) { case "Identifier": case "MemberExpression": return expr case "ParenthesizedExpression": expr.expression = this.checkLVal(expr.expression) return expr default: return this.dummyIdent() } } lp.parseExpression = function(noIn) { let start = this.storeCurrentPos() let expr = this.parseMaybeAssign(noIn) if (this.tok.type === tt.comma) { let node = this.startNodeAt(start) node.expressions = [expr] while (this.eat(tt.comma)) node.expressions.push(this.parseMaybeAssign(noIn)) return this.finishNode(node, "SequenceExpression") } return expr } lp.parseParenExpression = function() { this.pushCx() this.expect(tt.parenL) let val = this.parseExpression() this.popCx() this.expect(tt.parenR) return val } lp.parseMaybeAssign = function(noIn) { if (this.toks.isContextual("yield")) { let node = this.startNode() this.next() if (this.semicolon() || this.canInsertSemicolon() || (this.tok.type != tt.star && !this.tok.type.startsExpr)) { node.delegate = false node.argument = null } else { node.delegate = this.eat(tt.star) node.argument = this.parseMaybeAssign() } return this.finishNode(node, "YieldExpression") } let start = this.storeCurrentPos() let left = this.parseMaybeConditional(noIn) if (this.tok.type.isAssign) { let node = this.startNodeAt(start) node.operator = this.tok.value node.left = this.tok.type === tt.eq ? this.toAssignable(left) : this.checkLVal(left) this.next() node.right = this.parseMaybeAssign(noIn) return this.finishNode(node, "AssignmentExpression") } return left } lp.parseMaybeConditional = function(noIn) { let start = this.storeCurrentPos() let expr = this.parseExprOps(noIn) if (this.eat(tt.question)) { let node = this.startNodeAt(start) node.test = expr node.consequent = this.parseMaybeAssign() node.alternate = this.expect(tt.colon) ? this.parseMaybeAssign(noIn) : this.dummyIdent() return this.finishNode(node, "ConditionalExpression") } return expr } lp.parseExprOps = function(noIn) { let start = this.storeCurrentPos() let indent = this.curIndent, line = this.curLineStart return this.parseExprOp(this.parseMaybeUnary(false), start, -1, noIn, indent, line) } lp.parseExprOp = function(left, start, minPrec, noIn, indent, line) { if (this.curLineStart != line && this.curIndent < indent && this.tokenStartsLine()) return left let prec = this.tok.type.binop if (prec != null && (!noIn || this.tok.type !== tt._in)) { if (prec > minPrec) { let node = this.startNodeAt(start) node.left = left node.operator = this.tok.value this.next() if (this.curLineStart != line && this.curIndent < indent && this.tokenStartsLine()) { node.right = this.dummyIdent() } else { let rightStart = this.storeCurrentPos() node.right = this.parseExprOp(this.parseMaybeUnary(false), rightStart, prec, noIn, indent, line) } this.finishNode(node, /&&|\|\|/.test(node.operator) ? "LogicalExpression" : "BinaryExpression") return this.parseExprOp(node, start, minPrec, noIn, indent, line) } } return left } lp.parseMaybeUnary = function(sawUnary) { let start = this.storeCurrentPos(), expr if (this.options.ecmaVersion >= 8 && this.inAsync && this.toks.isContextual("await")) { expr = this.parseAwait() sawUnary = true } else if (this.tok.type.prefix) { let node = this.startNode(), update = this.tok.type === tt.incDec if (!update) sawUnary = true node.operator = this.tok.value node.prefix = true this.next() node.argument = this.parseMaybeUnary(true) if (update) node.argument = this.checkLVal(node.argument) expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression") } else if (this.tok.type === tt.ellipsis) { let node = this.startNode() this.next() node.argument = this.parseMaybeUnary(sawUnary) expr = this.finishNode(node, "SpreadElement") } else { expr = this.parseExprSubscripts() while (this.tok.type.postfix && !this.canInsertSemicolon()) { let node = this.startNodeAt(start) node.operator = this.tok.value node.prefix = false node.argument = this.checkLVal(expr) this.next() expr = this.finishNode(node, "UpdateExpression") } } if (!sawUnary && this.eat(tt.starstar)) { let node = this.startNodeAt(start) node.operator = "**" node.left = expr node.right = this.parseMaybeUnary(false) return this.finishNode(node, "BinaryExpression") } return expr } lp.parseExprSubscripts = function() { let start = this.storeCurrentPos() return this.parseSubscripts(this.parseExprAtom(), start, false, this.curIndent, this.curLineStart) } lp.parseSubscripts = function(base, start, noCalls, startIndent, line) { for (;;) { if (this.curLineStart != line && this.curIndent <= startIndent && this.tokenStartsLine()) { if (this.tok.type == tt.dot && this.curIndent == startIndent) --startIndent else return base } let maybeAsyncArrow = base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon() if (this.eat(tt.dot)) { let node = this.startNodeAt(start) node.object = base if (this.curLineStart != line && this.curIndent <= startIndent && this.tokenStartsLine()) node.property = this.dummyIdent() else node.property = this.parsePropertyAccessor() || this.dummyIdent() node.computed = false base = this.finishNode(node, "MemberExpression") } else if (this.tok.type == tt.bracketL) { this.pushCx() this.next() let node = this.startNodeAt(start) node.object = base node.property = this.parseExpression() node.computed = true this.popCx() this.expect(tt.bracketR) base = this.finishNode(node, "MemberExpression") } else if (!noCalls && this.tok.type == tt.parenL) { let exprList = this.parseExprList(tt.parenR) if (maybeAsyncArrow && this.eat(tt.arrow)) return this.parseArrowExpression(this.startNodeAt(start), exprList, true) let node = this.startNodeAt(start) node.callee = base node.arguments = exprList base = this.finishNode(node, "CallExpression") } else if (this.tok.type == tt.backQuote) { let node = this.startNodeAt(start) node.tag = base node.quasi = this.parseTemplate() base = this.finishNode(node, "TaggedTemplateExpression") } else { return base } } } lp.parseExprAtom = function() { let node switch (this.tok.type) { case tt._this: case tt._super: let type = this.tok.type === tt._this ? "ThisExpression" : "Super" node = this.startNode() this.next() return this.finishNode(node, type) case tt.name: let start = this.storeCurrentPos() let id = this.parseIdent() let isAsync = false if (id.name === "async" && !this.canInsertSemicolon()) { if (this.eat(tt._function)) return this.parseFunction(this.startNodeAt(start), false, true) if (this.tok.type === tt.name) { id = this.parseIdent() isAsync = true } } return this.eat(tt.arrow) ? this.parseArrowExpression(this.startNodeAt(start), [id], isAsync) : id case tt.regexp: node = this.startNode() let val = this.tok.value node.regex = {pattern: val.pattern, flags: val.flags} node.value = val.value node.raw = this.input.slice(this.tok.start, this.tok.end) this.next() return this.finishNode(node, "Literal") case tt.num: case tt.string: node = this.startNode() node.value = this.tok.value node.raw = this.input.slice(this.tok.start, this.tok.end) this.next() return this.finishNode(node, "Literal") case tt._null: case tt._true: case tt._false: node = this.startNode() node.value = this.tok.type === tt._null ? null : this.tok.type === tt._true node.raw = this.tok.type.keyword this.next() return this.finishNode(node, "Literal") case tt.parenL: let parenStart = this.storeCurrentPos() this.next() let inner = this.parseExpression() this.expect(tt.parenR) if (this.eat(tt.arrow)) { // (a,)=>a // SequenceExpression makes dummy in the last hole. Drop the dummy. let params = inner.expressions || [inner] if (params.length && isDummy(params[params.length - 1])) params.pop() return this.parseArrowExpression(this.startNodeAt(parenStart), params) } if (this.options.preserveParens) { let par = this.startNodeAt(parenStart) par.expression = inner inner = this.finishNode(par, "ParenthesizedExpression") } return inner case tt.bracketL: node = this.startNode() node.elements = this.parseExprList(tt.bracketR, true) return this.finishNode(node, "ArrayExpression") case tt.braceL: return this.parseObj() case tt._class: return this.parseClass(false) case tt._function: node = this.startNode() this.next() return this.parseFunction(node, false) case tt._new: return this.parseNew() case tt.backQuote: return this.parseTemplate() default: return this.dummyIdent() } } lp.parseNew = function() { let node = this.startNode(), startIndent = this.curIndent, line = this.curLineStart let meta = this.parseIdent(true) if (this.options.ecmaVersion >= 6 && this.eat(tt.dot)) { node.meta = meta node.property = this.parseIdent(true) return this.finishNode(node, "MetaProperty") } let start = this.storeCurrentPos() node.callee = this.parseSubscripts(this.parseExprAtom(), start, true, startIndent, line) if (this.tok.type == tt.parenL) { node.arguments = this.parseExprList(tt.parenR) } else { node.arguments = [] } return this.finishNode(node, "NewExpression") } lp.parseTemplateElement = function() { let elem = this.startNode() // The loose parser accepts invalid unicode escapes even in untagged templates. if (this.tok.type === tt.invalidTemplate) { elem.value = { raw: this.tok.value, cooked: null } } else { elem.value = { raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, "\n"), cooked: this.tok.value } } this.next() elem.tail = this.tok.type === tt.backQuote return this.finishNode(elem, "TemplateElement") } lp.parseTemplate = function() { let node = this.startNode() this.next() node.expressions = [] let curElt = this.parseTemplateElement() node.quasis = [curElt] while (!curElt.tail) { this.next() node.expressions.push(this.parseExpression()) if (this.expect(tt.braceR)) { curElt = this.parseTemplateElement() } else { curElt = this.startNode() curElt.value = {cooked: "", raw: ""} curElt.tail = true this.finishNode(curElt, "TemplateElement") } node.quasis.push(curElt) } this.expect(tt.backQuote) return this.finishNode(node, "TemplateLiteral") } lp.parseObj = function() { let node = this.startNode() node.properties = [] this.pushCx() let indent = this.curIndent + 1, line = this.curLineStart this.eat(tt.braceL) if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart } while (!this.closes(tt.braceR, indent, line)) { let prop = this.startNode(), isGenerator, isAsync, start if (this.options.ecmaVersion >= 9 && this.eat(tt.ellipsis)) { prop.argument = this.parseMaybeAssign() node.properties.push(this.finishNode(prop, "SpreadElement")) this.eat(tt.comma) continue } if (this.options.ecmaVersion >= 6) { start = this.storeCurrentPos() prop.method = false prop.shorthand = false isGenerator = this.eat(tt.star) } this.parsePropertyName(prop) if (this.toks.isAsyncProp(prop)) { isAsync = true isGenerator = this.options.ecmaVersion >= 9 && this.eat(tt.star) this.parsePropertyName(prop) } else { isAsync = false } if (isDummy(prop.key)) { if (isDummy(this.parseMaybeAssign())) this.next(); this.eat(tt.comma); continue } if (this.eat(tt.colon)) { prop.kind = "init" prop.value = this.parseMaybeAssign() } else if (this.options.ecmaVersion >= 6 && (this.tok.type === tt.parenL || this.tok.type === tt.braceL)) { prop.kind = "init" prop.method = true prop.value = this.parseMethod(isGenerator, isAsync) } else if (this.options.ecmaVersion >= 5 && prop.key.type === "Identifier" && !prop.computed && (prop.key.name === "get" || prop.key.name === "set") && (this.tok.type != tt.comma && this.tok.type != tt.braceR && this.tok.type != tt.eq)) { prop.kind = prop.key.name this.parsePropertyName(prop) prop.value = this.parseMethod(false) } else { prop.kind = "init" if (this.options.ecmaVersion >= 6) { if (this.eat(tt.eq)) { let assign = this.startNodeAt(start) assign.operator = "=" assign.left = prop.key assign.right = this.parseMaybeAssign() prop.value = this.finishNode(assign, "AssignmentExpression") } else { prop.value = prop.key } } else { prop.value = this.dummyIdent() } prop.shorthand = true } node.properties.push(this.finishNode(prop, "Property")) this.eat(tt.comma) } this.popCx() if (!this.eat(tt.braceR)) { // If there is no closing brace, make the node span to the start // of the next token (this is useful for Tern) this.last.end = this.tok.start if (this.options.locations) this.last.loc.end = this.tok.loc.start } return this.finishNode(node, "ObjectExpression") } lp.parsePropertyName = function(prop) { if (this.options.ecmaVersion >= 6) { if (this.eat(tt.bracketL)) { prop.computed = true prop.key = this.parseExpression() this.expect(tt.bracketR) return } else { prop.computed = false } } let key = (this.tok.type === tt.num || this.tok.type === tt.string) ? this.parseExprAtom() : this.parseIdent() prop.key = key || this.dummyIdent() } lp.parsePropertyAccessor = function() { if (this.tok.type === tt.name || this.tok.type.keyword) return this.parseIdent() } lp.parseIdent = function() { let name = this.tok.type === tt.name ? this.tok.value : this.tok.type.keyword if (!name) return this.dummyIdent() let node = this.startNode() this.next() node.name = name return this.finishNode(node, "Identifier") } lp.initFunction = function(node) { node.id = null node.params = [] if (this.options.ecmaVersion >= 6) { node.generator = false node.expression = false } if (this.options.ecmaVersion >= 8) node.async = false } // Convert existing expression atom to assignable pattern // if possible. lp.toAssignable = function(node, binding) { if (!node || node.type == "Identifier" || (node.type == "MemberExpression" && !binding)) { // Okay } else if (node.type == "ParenthesizedExpression") { this.toAssignable(node.expression, binding) } else if (this.options.ecmaVersion < 6) { return this.dummyIdent() } else if (node.type == "ObjectExpression") { node.type = "ObjectPattern" for (let prop of node.properties) this.toAssignable(prop, binding) } else if (node.type == "ArrayExpression") { node.type = "ArrayPattern" this.toAssignableList(node.elements, binding) } else if (node.type == "Property") { this.toAssignable(node.value, binding) } else if (node.type == "SpreadElement") { node.type = "RestElement" this.toAssignable(node.argument, binding) } else if (node.type == "AssignmentExpression") { node.type = "AssignmentPattern" delete node.operator } else { return this.dummyIdent() } return node } lp.toAssignableList = function(exprList, binding) { for (let expr of exprList) this.toAssignable(expr, binding) return exprList } lp.parseFunctionParams = function(params) { params = this.parseExprList(tt.parenR) return this.toAssignableList(params, true) } lp.parseMethod = function(isGenerator, isAsync) { let node = this.startNode(), oldInAsync = this.inAsync this.initFunction(node) if (this.options.ecmaVersion >= 6) node.generator = !!isGenerator if (this.options.ecmaVersion >= 8) node.async = !!isAsync this.inAsync = node.async node.params = this.parseFunctionParams() node.body = this.parseBlock() this.toks.adaptDirectivePrologue(node.body.body) this.inAsync = oldInAsync return this.finishNode(node, "FunctionExpression") } lp.parseArrowExpression = function(node, params, isAsync) { let oldInAsync = this.inAsync this.initFunction(node) if (this.options.ecmaVersion >= 8) node.async = !!isAsync this.inAsync = node.async node.params = this.toAssignableList(params, true) node.expression = this.tok.type !== tt.braceL if (node.expression) { node.body = this.parseMaybeAssign() } else { node.body = this.parseBlock() this.toks.adaptDirectivePrologue(node.body.body) } this.inAsync = oldInAsync return this.finishNode(node, "ArrowFunctionExpression") } lp.parseExprList = function(close, allowEmpty) { this.pushCx() let indent = this.curIndent, line = this.curLineStart, elts = [] this.next() // Opening bracket while (!this.closes(close, indent + 1, line)) { if (this.eat(tt.comma)) { elts.push(allowEmpty ? null : this.dummyIdent()) continue } let elt = this.parseMaybeAssign() if (isDummy(elt)) { if (this.closes(close, indent, line)) break this.next() } else { elts.push(elt) } this.eat(tt.comma) } this.popCx() if (!this.eat(close)) { // If there is no closing brace, make the node span to the start // of the next token (this is useful for Tern) this.last.end = this.tok.start if (this.options.locations) this.last.loc.end = this.tok.loc.start } return elts } lp.parseAwait = function() { let node = this.startNode() this.next() node.argument = this.parseMaybeUnary() return this.finishNode(node, "AwaitExpression") } acorn-5.5.3/src/loose/index.js000066400000000000000000000033331325020065300162010ustar00rootroot00000000000000// Acorn: Loose parser // // This module provides an alternative parser (`parse_dammit`) that // exposes that same interface as `parse`, but will try to parse // anything as JavaScript, repairing syntax error the best it can. // There are circumstances in which it will raise an error and give // up, but they are very rare. The resulting AST will be a mostly // valid JavaScript AST (as per the [Mozilla parser API][api], except // that: // // - Return outside functions is allowed // // - Label consistency (no conflicts, break only to existing labels) // is not enforced. // // - Bogus Identifier nodes with a name of `"✖"` are inserted whenever // the parser got too confused to return anything meaningful. // // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API // // The expected use for this is to *first* try `acorn.parse`, and only // if that fails switch to `parse_dammit`. The loose parser might // parse badly indented code incorrectly, so **don't** use it as // your default parser. // // Quite a lot of acorn.js is duplicated here. The alternative was to // add a *lot* of extra cruft to that file, making it less readable // and slower. Copying and editing the code allowed me to make // invasive changes and simplifications without creating a complicated // tangle. import {addLooseExports, defaultOptions} from "../index" import {LooseParser, pluginsLoose} from "./state" import "./tokenize" import "./statement" import "./expression" export {LooseParser, pluginsLoose} from "./state" defaultOptions.tabSize = 4 // eslint-disable-next-line camelcase export function parse_dammit(input, options) { return new LooseParser(input, options).parse() } addLooseExports(parse_dammit, LooseParser, pluginsLoose) acorn-5.5.3/src/loose/parseutil.js000066400000000000000000000000741325020065300171010ustar00rootroot00000000000000export function isDummy(node) { return node.name == "✖" } acorn-5.5.3/src/loose/state.js000066400000000000000000000103051325020065300162070ustar00rootroot00000000000000import {tokenizer, SourceLocation, tokTypes as tt, Node, lineBreak, isNewLine} from "../index" function noop() {} // Registered plugins export const pluginsLoose = {} export class LooseParser { constructor(input, options = {}) { this.toks = tokenizer(input, options) this.options = this.toks.options this.input = this.toks.input this.tok = this.last = {type: tt.eof, start: 0, end: 0} this.tok.validateRegExpFlags = noop this.tok.validateRegExpPattern = noop if (this.options.locations) { let here = this.toks.curPosition() this.tok.loc = new SourceLocation(this.toks, here, here) } this.ahead = [] // Tokens ahead this.context = [] // Indentation contexted this.curIndent = 0 this.curLineStart = 0 this.nextLineStart = this.lineEnd(this.curLineStart) + 1 this.inAsync = false // Load plugins this.options.pluginsLoose = options.pluginsLoose || {} this.loadPlugins(this.options.pluginsLoose) } startNode() { return new Node(this.toks, this.tok.start, this.options.locations ? this.tok.loc.start : null) } storeCurrentPos() { return this.options.locations ? [this.tok.start, this.tok.loc.start] : this.tok.start } startNodeAt(pos) { if (this.options.locations) { return new Node(this.toks, pos[0], pos[1]) } else { return new Node(this.toks, pos) } } finishNode(node, type) { node.type = type node.end = this.last.end if (this.options.locations) node.loc.end = this.last.loc.end if (this.options.ranges) node.range[1] = this.last.end return node } dummyNode(type) { let dummy = this.startNode() dummy.type = type dummy.end = dummy.start if (this.options.locations) dummy.loc.end = dummy.loc.start if (this.options.ranges) dummy.range[1] = dummy.start this.last = {type: tt.name, start: dummy.start, end: dummy.start, loc: dummy.loc} return dummy } dummyIdent() { let dummy = this.dummyNode("Identifier") dummy.name = "✖" return dummy } dummyString() { let dummy = this.dummyNode("Literal") dummy.value = dummy.raw = "✖" return dummy } eat(type) { if (this.tok.type === type) { this.next() return true } else { return false } } isContextual(name) { return this.tok.type === tt.name && this.tok.value === name } eatContextual(name) { return this.tok.value === name && this.eat(tt.name) } canInsertSemicolon() { return this.tok.type === tt.eof || this.tok.type === tt.braceR || lineBreak.test(this.input.slice(this.last.end, this.tok.start)) } semicolon() { return this.eat(tt.semi) } expect(type) { if (this.eat(type)) return true for (let i = 1; i <= 2; i++) { if (this.lookAhead(i).type == type) { for (let j = 0; j < i; j++) this.next() return true } } } pushCx() { this.context.push(this.curIndent) } popCx() { this.curIndent = this.context.pop() } lineEnd(pos) { while (pos < this.input.length && !isNewLine(this.input.charCodeAt(pos))) ++pos return pos } indentationAfter(pos) { for (let count = 0;; ++pos) { let ch = this.input.charCodeAt(pos) if (ch === 32) ++count else if (ch === 9) count += this.options.tabSize else return count } } closes(closeTok, indent, line, blockHeuristic) { if (this.tok.type === closeTok || this.tok.type === tt.eof) return true return line != this.curLineStart && this.curIndent < indent && this.tokenStartsLine() && (!blockHeuristic || this.nextLineStart >= this.input.length || this.indentationAfter(this.nextLineStart) < indent) } tokenStartsLine() { for (let p = this.tok.start - 1; p >= this.curLineStart; --p) { let ch = this.input.charCodeAt(p) if (ch !== 9 && ch !== 32) return false } return true } extend(name, f) { this[name] = f(this[name]) } loadPlugins(pluginConfigs) { for (let name in pluginConfigs) { let plugin = pluginsLoose[name] if (!plugin) throw new Error("Plugin '" + name + "' not found") plugin(this, pluginConfigs[name]) } } parse() { this.next() return this.parseTopLevel() } } acorn-5.5.3/src/loose/statement.js000066400000000000000000000362351325020065300171050ustar00rootroot00000000000000import {LooseParser} from "./state" import {isDummy} from "./parseutil" import {getLineInfo, tokTypes as tt} from "../index" const lp = LooseParser.prototype lp.parseTopLevel = function() { let node = this.startNodeAt(this.options.locations ? [0, getLineInfo(this.input, 0)] : 0) node.body = [] while (this.tok.type !== tt.eof) node.body.push(this.parseStatement()) this.toks.adaptDirectivePrologue(node.body) this.last = this.tok if (this.options.ecmaVersion >= 6) { node.sourceType = this.options.sourceType } return this.finishNode(node, "Program") } lp.parseStatement = function() { let starttype = this.tok.type, node = this.startNode(), kind if (this.toks.isLet()) { starttype = tt._var kind = "let" } switch (starttype) { case tt._break: case tt._continue: this.next() let isBreak = starttype === tt._break if (this.semicolon() || this.canInsertSemicolon()) { node.label = null } else { node.label = this.tok.type === tt.name ? this.parseIdent() : null this.semicolon() } return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") case tt._debugger: this.next() this.semicolon() return this.finishNode(node, "DebuggerStatement") case tt._do: this.next() node.body = this.parseStatement() node.test = this.eat(tt._while) ? this.parseParenExpression() : this.dummyIdent() this.semicolon() return this.finishNode(node, "DoWhileStatement") case tt._for: this.next() // `for` keyword let isAwait = this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await") this.pushCx() this.expect(tt.parenL) if (this.tok.type === tt.semi) return this.parseFor(node, null) let isLet = this.toks.isLet() if (isLet || this.tok.type === tt._var || this.tok.type === tt._const) { let init = this.parseVar(true, isLet ? "let" : this.tok.value) if (init.declarations.length === 1 && (this.tok.type === tt._in || this.isContextual("of"))) { if (this.options.ecmaVersion >= 9 && this.tok.type !== tt._in) { node.await = isAwait } return this.parseForIn(node, init) } return this.parseFor(node, init) } let init = this.parseExpression(true) if (this.tok.type === tt._in || this.isContextual("of")) { if (this.options.ecmaVersion >= 9 && this.tok.type !== tt._in) { node.await = isAwait } return this.parseForIn(node, this.toAssignable(init)) } return this.parseFor(node, init) case tt._function: this.next() return this.parseFunction(node, true) case tt._if: this.next() node.test = this.parseParenExpression() node.consequent = this.parseStatement() node.alternate = this.eat(tt._else) ? this.parseStatement() : null return this.finishNode(node, "IfStatement") case tt._return: this.next() if (this.eat(tt.semi) || this.canInsertSemicolon()) node.argument = null else { node.argument = this.parseExpression(); this.semicolon() } return this.finishNode(node, "ReturnStatement") case tt._switch: let blockIndent = this.curIndent, line = this.curLineStart this.next() node.discriminant = this.parseParenExpression() node.cases = [] this.pushCx() this.expect(tt.braceL) let cur while (!this.closes(tt.braceR, blockIndent, line, true)) { if (this.tok.type === tt._case || this.tok.type === tt._default) { let isCase = this.tok.type === tt._case if (cur) this.finishNode(cur, "SwitchCase") node.cases.push(cur = this.startNode()) cur.consequent = [] this.next() if (isCase) cur.test = this.parseExpression() else cur.test = null this.expect(tt.colon) } else { if (!cur) { node.cases.push(cur = this.startNode()) cur.consequent = [] cur.test = null } cur.consequent.push(this.parseStatement()) } } if (cur) this.finishNode(cur, "SwitchCase") this.popCx() this.eat(tt.braceR) return this.finishNode(node, "SwitchStatement") case tt._throw: this.next() node.argument = this.parseExpression() this.semicolon() return this.finishNode(node, "ThrowStatement") case tt._try: this.next() node.block = this.parseBlock() node.handler = null if (this.tok.type === tt._catch) { let clause = this.startNode() this.next() this.expect(tt.parenL) clause.param = this.toAssignable(this.parseExprAtom(), true) this.expect(tt.parenR) clause.body = this.parseBlock() node.handler = this.finishNode(clause, "CatchClause") } node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null if (!node.handler && !node.finalizer) return node.block return this.finishNode(node, "TryStatement") case tt._var: case tt._const: return this.parseVar(false, kind || this.tok.value) case tt._while: this.next() node.test = this.parseParenExpression() node.body = this.parseStatement() return this.finishNode(node, "WhileStatement") case tt._with: this.next() node.object = this.parseParenExpression() node.body = this.parseStatement() return this.finishNode(node, "WithStatement") case tt.braceL: return this.parseBlock() case tt.semi: this.next() return this.finishNode(node, "EmptyStatement") case tt._class: return this.parseClass(true) case tt._import: return this.parseImport() case tt._export: return this.parseExport() default: if (this.toks.isAsyncFunction()) { this.next() this.next() return this.parseFunction(node, true, true) } let expr = this.parseExpression() if (isDummy(expr)) { this.next() if (this.tok.type === tt.eof) return this.finishNode(node, "EmptyStatement") return this.parseStatement() } else if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon)) { node.body = this.parseStatement() node.label = expr return this.finishNode(node, "LabeledStatement") } else { node.expression = expr this.semicolon() return this.finishNode(node, "ExpressionStatement") } } } lp.parseBlock = function() { let node = this.startNode() this.pushCx() this.expect(tt.braceL) let blockIndent = this.curIndent, line = this.curLineStart node.body = [] while (!this.closes(tt.braceR, blockIndent, line, true)) node.body.push(this.parseStatement()) this.popCx() this.eat(tt.braceR) return this.finishNode(node, "BlockStatement") } lp.parseFor = function(node, init) { node.init = init node.test = node.update = null if (this.eat(tt.semi) && this.tok.type !== tt.semi) node.test = this.parseExpression() if (this.eat(tt.semi) && this.tok.type !== tt.parenR) node.update = this.parseExpression() this.popCx() this.expect(tt.parenR) node.body = this.parseStatement() return this.finishNode(node, "ForStatement") } lp.parseForIn = function(node, init) { let type = this.tok.type === tt._in ? "ForInStatement" : "ForOfStatement" this.next() node.left = init node.right = this.parseExpression() this.popCx() this.expect(tt.parenR) node.body = this.parseStatement() return this.finishNode(node, type) } lp.parseVar = function(noIn, kind) { let node = this.startNode() node.kind = kind this.next() node.declarations = [] do { let decl = this.startNode() decl.id = this.options.ecmaVersion >= 6 ? this.toAssignable(this.parseExprAtom(), true) : this.parseIdent() decl.init = this.eat(tt.eq) ? this.parseMaybeAssign(noIn) : null node.declarations.push(this.finishNode(decl, "VariableDeclarator")) } while (this.eat(tt.comma)) if (!node.declarations.length) { let decl = this.startNode() decl.id = this.dummyIdent() node.declarations.push(this.finishNode(decl, "VariableDeclarator")) } if (!noIn) this.semicolon() return this.finishNode(node, "VariableDeclaration") } lp.parseClass = function(isStatement) { let node = this.startNode() this.next() if (this.tok.type === tt.name) node.id = this.parseIdent() else if (isStatement === true) node.id = this.dummyIdent() else node.id = null node.superClass = this.eat(tt._extends) ? this.parseExpression() : null node.body = this.startNode() node.body.body = [] this.pushCx() let indent = this.curIndent + 1, line = this.curLineStart this.eat(tt.braceL) if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart } while (!this.closes(tt.braceR, indent, line)) { if (this.semicolon()) continue let method = this.startNode(), isGenerator, isAsync if (this.options.ecmaVersion >= 6) { method.static = false isGenerator = this.eat(tt.star) } this.parsePropertyName(method) if (isDummy(method.key)) { if (isDummy(this.parseMaybeAssign())) this.next(); this.eat(tt.comma); continue } if (method.key.type === "Identifier" && !method.computed && method.key.name === "static" && (this.tok.type != tt.parenL && this.tok.type != tt.braceL)) { method.static = true isGenerator = this.eat(tt.star) this.parsePropertyName(method) } else { method.static = false } if (!method.computed && method.key.type === "Identifier" && method.key.name === "async" && this.tok.type !== tt.parenL && !this.canInsertSemicolon()) { isAsync = true isGenerator = this.options.ecmaVersion >= 9 && this.eat(tt.star) this.parsePropertyName(method) } else { isAsync = false } if (this.options.ecmaVersion >= 5 && method.key.type === "Identifier" && !method.computed && (method.key.name === "get" || method.key.name === "set") && this.tok.type !== tt.parenL && this.tok.type !== tt.braceL) { method.kind = method.key.name this.parsePropertyName(method) method.value = this.parseMethod(false) } else { if (!method.computed && !method.static && !isGenerator && !isAsync && ( method.key.type === "Identifier" && method.key.name === "constructor" || method.key.type === "Literal" && method.key.value === "constructor")) { method.kind = "constructor" } else { method.kind = "method" } method.value = this.parseMethod(isGenerator, isAsync) } node.body.body.push(this.finishNode(method, "MethodDefinition")) } this.popCx() if (!this.eat(tt.braceR)) { // If there is no closing brace, make the node span to the start // of the next token (this is useful for Tern) this.last.end = this.tok.start if (this.options.locations) this.last.loc.end = this.tok.loc.start } this.semicolon() this.finishNode(node.body, "ClassBody") return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") } lp.parseFunction = function(node, isStatement, isAsync) { let oldInAsync = this.inAsync this.initFunction(node) if (this.options.ecmaVersion >= 6) { node.generator = this.eat(tt.star) } if (this.options.ecmaVersion >= 8) { node.async = !!isAsync } if (this.tok.type === tt.name) node.id = this.parseIdent() else if (isStatement === true) node.id = this.dummyIdent() this.inAsync = node.async node.params = this.parseFunctionParams() node.body = this.parseBlock() this.toks.adaptDirectivePrologue(node.body.body) this.inAsync = oldInAsync return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") } lp.parseExport = function() { let node = this.startNode() this.next() if (this.eat(tt.star)) { node.source = this.eatContextual("from") ? this.parseExprAtom() : this.dummyString() return this.finishNode(node, "ExportAllDeclaration") } if (this.eat(tt._default)) { // export default (function foo() {}) // This is FunctionExpression. let isAsync if (this.tok.type === tt._function || (isAsync = this.toks.isAsyncFunction())) { let fNode = this.startNode() this.next() if (isAsync) this.next() node.declaration = this.parseFunction(fNode, "nullableID", isAsync) } else if (this.tok.type === tt._class) { node.declaration = this.parseClass("nullableID") } else { node.declaration = this.parseMaybeAssign() this.semicolon() } return this.finishNode(node, "ExportDefaultDeclaration") } if (this.tok.type.keyword || this.toks.isLet() || this.toks.isAsyncFunction()) { node.declaration = this.parseStatement() node.specifiers = [] node.source = null } else { node.declaration = null node.specifiers = this.parseExportSpecifierList() node.source = this.eatContextual("from") ? this.parseExprAtom() : null this.semicolon() } return this.finishNode(node, "ExportNamedDeclaration") } lp.parseImport = function() { let node = this.startNode() this.next() if (this.tok.type === tt.string) { node.specifiers = [] node.source = this.parseExprAtom() } else { let elt if (this.tok.type === tt.name && this.tok.value !== "from") { elt = this.startNode() elt.local = this.parseIdent() this.finishNode(elt, "ImportDefaultSpecifier") this.eat(tt.comma) } node.specifiers = this.parseImportSpecifierList() node.source = this.eatContextual("from") && this.tok.type == tt.string ? this.parseExprAtom() : this.dummyString() if (elt) node.specifiers.unshift(elt) } this.semicolon() return this.finishNode(node, "ImportDeclaration") } lp.parseImportSpecifierList = function() { let elts = [] if (this.tok.type === tt.star) { let elt = this.startNode() this.next() elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent() elts.push(this.finishNode(elt, "ImportNamespaceSpecifier")) } else { let indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart this.pushCx() this.eat(tt.braceL) if (this.curLineStart > continuedLine) continuedLine = this.curLineStart while (!this.closes(tt.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { let elt = this.startNode() if (this.eat(tt.star)) { elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent() this.finishNode(elt, "ImportNamespaceSpecifier") } else { if (this.isContextual("from")) break elt.imported = this.parseIdent() if (isDummy(elt.imported)) break elt.local = this.eatContextual("as") ? this.parseIdent() : elt.imported this.finishNode(elt, "ImportSpecifier") } elts.push(elt) this.eat(tt.comma) } this.eat(tt.braceR) this.popCx() } return elts } lp.parseExportSpecifierList = function() { let elts = [] let indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart this.pushCx() this.eat(tt.braceL) if (this.curLineStart > continuedLine) continuedLine = this.curLineStart while (!this.closes(tt.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { if (this.isContextual("from")) break let elt = this.startNode() elt.local = this.parseIdent() if (isDummy(elt.local)) break elt.exported = this.eatContextual("as") ? this.parseIdent() : elt.local this.finishNode(elt, "ExportSpecifier") elts.push(elt) this.eat(tt.comma) } this.eat(tt.braceR) this.popCx() return elts } acorn-5.5.3/src/loose/tokenize.js000066400000000000000000000072311325020065300167230ustar00rootroot00000000000000import {tokTypes as tt, Token, isNewLine, SourceLocation, getLineInfo, lineBreakG} from "../index" import {LooseParser} from "./state" const lp = LooseParser.prototype function isSpace(ch) { return (ch < 14 && ch > 8) || ch === 32 || ch === 160 || isNewLine(ch) } lp.next = function() { this.last = this.tok if (this.ahead.length) this.tok = this.ahead.shift() else this.tok = this.readToken() if (this.tok.start >= this.nextLineStart) { while (this.tok.start >= this.nextLineStart) { this.curLineStart = this.nextLineStart this.nextLineStart = this.lineEnd(this.curLineStart) + 1 } this.curIndent = this.indentationAfter(this.curLineStart) } } lp.readToken = function() { for (;;) { try { this.toks.next() if (this.toks.type === tt.dot && this.input.substr(this.toks.end, 1) === "." && this.options.ecmaVersion >= 6) { this.toks.end++ this.toks.type = tt.ellipsis } return new Token(this.toks) } catch (e) { if (!(e instanceof SyntaxError)) throw e // Try to skip some text, based on the error message, and then continue let msg = e.message, pos = e.raisedAt, replace = true if (/unterminated/i.test(msg)) { pos = this.lineEnd(e.pos + 1) if (/string/.test(msg)) { replace = {start: e.pos, end: pos, type: tt.string, value: this.input.slice(e.pos + 1, pos)} } else if (/regular expr/i.test(msg)) { let re = this.input.slice(e.pos, pos) try { re = new RegExp(re) } catch (e) { /* ignore compilation error due to new syntax */ } replace = {start: e.pos, end: pos, type: tt.regexp, value: re} } else if (/template/.test(msg)) { replace = { start: e.pos, end: pos, type: tt.template, value: this.input.slice(e.pos, pos) } } else { replace = false } } else if (/invalid (unicode|regexp|number)|expecting unicode|octal literal|is reserved|directly after number|expected number in radix/i.test(msg)) { while (pos < this.input.length && !isSpace(this.input.charCodeAt(pos))) ++pos } else if (/character escape|expected hexadecimal/i.test(msg)) { while (pos < this.input.length) { let ch = this.input.charCodeAt(pos++) if (ch === 34 || ch === 39 || isNewLine(ch)) break } } else if (/unexpected character/i.test(msg)) { pos++ replace = false } else if (/regular expression/i.test(msg)) { replace = true } else { throw e } this.resetTo(pos) if (replace === true) replace = {start: pos, end: pos, type: tt.name, value: "✖"} if (replace) { if (this.options.locations) replace.loc = new SourceLocation( this.toks, getLineInfo(this.input, replace.start), getLineInfo(this.input, replace.end)) return replace } } } } lp.resetTo = function(pos) { this.toks.pos = pos let ch = this.input.charAt(pos - 1) this.toks.exprAllowed = !ch || /[[{(,;:?/*=+\-~!|&%^<>]/.test(ch) || /[enwfd]/.test(ch) && /\b(case|else|return|throw|new|in|(instance|type)?of|delete|void)$/.test(this.input.slice(pos - 10, pos)) if (this.options.locations) { this.toks.curLine = 1 this.toks.lineStart = lineBreakG.lastIndex = 0 let match while ((match = lineBreakG.exec(this.input)) && match.index < pos) { ++this.toks.curLine this.toks.lineStart = match.index + match[0].length } } } lp.lookAhead = function(n) { while (n > this.ahead.length) this.ahead.push(this.readToken()) return this.ahead[n - 1] } acorn-5.5.3/src/lval.js000066400000000000000000000170661325020065300147170ustar00rootroot00000000000000import {types as tt} from "./tokentype" import {Parser} from "./state" import {has} from "./util" const pp = Parser.prototype // Convert existing expression atom to assignable pattern // if possible. pp.toAssignable = function(node, isBinding, refDestructuringErrors) { if (this.options.ecmaVersion >= 6 && node) { switch (node.type) { case "Identifier": if (this.inAsync && node.name === "await") this.raise(node.start, "Can not use 'await' as identifier inside an async function") break case "ObjectPattern": case "ArrayPattern": case "RestElement": break case "ObjectExpression": node.type = "ObjectPattern" if (refDestructuringErrors) this.checkPatternErrors(refDestructuringErrors, true) for (let prop of node.properties) { this.toAssignable(prop, isBinding) // Early error: // AssignmentRestProperty[Yield, Await] : // `...` DestructuringAssignmentTarget[Yield, Await] // // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|. if ( prop.type === "RestElement" && (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern") ) { this.raise(prop.argument.start, "Unexpected token") } } break case "Property": // AssignmentProperty has type == "Property" if (node.kind !== "init") this.raise(node.key.start, "Object pattern can't contain getter or setter") this.toAssignable(node.value, isBinding) break case "ArrayExpression": node.type = "ArrayPattern" if (refDestructuringErrors) this.checkPatternErrors(refDestructuringErrors, true) this.toAssignableList(node.elements, isBinding) break case "SpreadElement": node.type = "RestElement" this.toAssignable(node.argument, isBinding) if (node.argument.type === "AssignmentPattern") this.raise(node.argument.start, "Rest elements cannot have a default value") break case "AssignmentExpression": if (node.operator !== "=") this.raise(node.left.end, "Only '=' operator can be used for specifying default value.") node.type = "AssignmentPattern" delete node.operator this.toAssignable(node.left, isBinding) // falls through to AssignmentPattern case "AssignmentPattern": break case "ParenthesizedExpression": this.toAssignable(node.expression, isBinding) break case "MemberExpression": if (!isBinding) break default: this.raise(node.start, "Assigning to rvalue") } } else if (refDestructuringErrors) this.checkPatternErrors(refDestructuringErrors, true) return node } // Convert list of expression atoms to binding list. pp.toAssignableList = function(exprList, isBinding) { let end = exprList.length for (let i = 0; i < end; i++) { let elt = exprList[i] if (elt) this.toAssignable(elt, isBinding) } if (end) { let last = exprList[end - 1] if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier") this.unexpected(last.argument.start) } return exprList } // Parses spread element. pp.parseSpread = function(refDestructuringErrors) { let node = this.startNode() this.next() node.argument = this.parseMaybeAssign(false, refDestructuringErrors) return this.finishNode(node, "SpreadElement") } pp.parseRestBinding = function() { let node = this.startNode() this.next() // RestElement inside of a function parameter must be an identifier if (this.options.ecmaVersion === 6 && this.type !== tt.name) this.unexpected() node.argument = this.parseBindingAtom() return this.finishNode(node, "RestElement") } // Parses lvalue (assignable) atom. pp.parseBindingAtom = function() { if (this.options.ecmaVersion >= 6) { switch (this.type) { case tt.bracketL: let node = this.startNode() this.next() node.elements = this.parseBindingList(tt.bracketR, true, true) return this.finishNode(node, "ArrayPattern") case tt.braceL: return this.parseObj(true) } } return this.parseIdent() } pp.parseBindingList = function(close, allowEmpty, allowTrailingComma) { let elts = [], first = true while (!this.eat(close)) { 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) { let rest = this.parseRestBinding() this.parseBindingListItem(rest) elts.push(rest) if (this.type === tt.comma) this.raise(this.start, "Comma is not permitted after the rest element") this.expect(close) break } else { let elem = this.parseMaybeDefault(this.start, this.startLoc) this.parseBindingListItem(elem) elts.push(elem) } } return elts } pp.parseBindingListItem = function(param) { return param } // Parses assignment pattern around given atom if possible. pp.parseMaybeDefault = function(startPos, startLoc, left) { left = left || this.parseBindingAtom() if (this.options.ecmaVersion < 6 || !this.eat(tt.eq)) return left let node = this.startNodeAt(startPos, startLoc) node.left = left node.right = this.parseMaybeAssign() return this.finishNode(node, "AssignmentPattern") } // Verify that a node is an lval — something that can be assigned // to. // bindingType can be either: // 'var' indicating that the lval creates a 'var' binding // 'let' indicating that the lval creates a lexical ('let' or 'const') binding // 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references pp.checkLVal = function(expr, bindingType, checkClashes) { switch (expr.type) { case "Identifier": if (this.strict && this.reservedWordsStrictBind.test(expr.name)) this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode") if (checkClashes) { if (has(checkClashes, expr.name)) this.raiseRecoverable(expr.start, "Argument name clash") checkClashes[expr.name] = true } if (bindingType && bindingType !== "none") { if ( bindingType === "var" && !this.canDeclareVarName(expr.name) || bindingType !== "var" && !this.canDeclareLexicalName(expr.name) ) { this.raiseRecoverable(expr.start, `Identifier '${expr.name}' has already been declared`) } if (bindingType === "var") { this.declareVarName(expr.name) } else { this.declareLexicalName(expr.name) } } break case "MemberExpression": if (bindingType) this.raiseRecoverable(expr.start, "Binding member expression") break case "ObjectPattern": for (let prop of expr.properties) this.checkLVal(prop, bindingType, checkClashes) break case "Property": // AssignmentProperty has type == "Property" this.checkLVal(expr.value, bindingType, checkClashes) break case "ArrayPattern": for (let elem of expr.elements) { if (elem) this.checkLVal(elem, bindingType, checkClashes) } break case "AssignmentPattern": this.checkLVal(expr.left, bindingType, checkClashes) break case "RestElement": this.checkLVal(expr.argument, bindingType, checkClashes) break case "ParenthesizedExpression": this.checkLVal(expr.expression, bindingType, checkClashes) break default: this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue") } } acorn-5.5.3/src/node.js000066400000000000000000000022521325020065300146750ustar00rootroot00000000000000import {Parser} from "./state" import {SourceLocation} from "./locutil" export class Node { constructor(parser, pos, loc) { this.type = "" this.start = pos this.end = 0 if (parser.options.locations) this.loc = new SourceLocation(parser, loc) if (parser.options.directSourceFile) this.sourceFile = parser.options.directSourceFile if (parser.options.ranges) this.range = [pos, 0] } } // Start an AST node, attaching a start offset. const pp = Parser.prototype pp.startNode = function() { return new Node(this, this.start, this.startLoc) } pp.startNodeAt = function(pos, loc) { return new Node(this, pos, loc) } // Finish an AST node, adding `type` and `end` properties. function finishNodeAt(node, type, pos, loc) { node.type = type node.end = pos if (this.options.locations) node.loc.end = loc if (this.options.ranges) node.range[1] = pos return node } pp.finishNode = function(node, type) { return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) } // Finish node at given position pp.finishNodeAt = function(node, type, pos, loc) { return finishNodeAt.call(this, node, type, pos, loc) } acorn-5.5.3/src/options.js000066400000000000000000000121721325020065300154450ustar00rootroot00000000000000import {has, isArray} from "./util" import {SourceLocation} from "./locutil" // A second optional argument can be given to further configure // the parser process. These options are recognized: export const defaultOptions = { // `ecmaVersion` indicates the ECMAScript version to parse. Must // be either 3, 5, 6 (2015), 7 (2016), or 8 (2017). This influences support // for strict mode, the set of reserved words, and support for // new syntax features. The default is 7. ecmaVersion: 7, // `sourceType` indicates the mode the code should be parsed in. // Can be either `"script"` or `"module"`. This influences global // strict mode and parsing of `import` and `export` declarations. sourceType: "script", // `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 only enforced if ecmaVersion >= 5. // Set `allowReserved` to a boolean value to explicitly turn this on // an off. When this option has the value "never", reserved words // and keywords can also not be used as property names. allowReserved: null, // When enabled, a return at the top level is not considered an // error. allowReturnOutsideFunction: false, // When enabled, import/export statements are not constrained to // appearing at the top of the program. allowImportExportEverywhere: false, // When enabled, hashbang directive in the beginning of file // is allowed and treated as a line comment. allowHashBang: false, // When `locations` is on, `loc` properties holding objects with // `start` and `end` properties in `{line, column}` form (with // line being 1-based and column 0-based) will be attached to the // nodes. locations: false, // A function can be passed as `onToken` option, which will // cause Acorn to call that function with object in the same // format as tokens returned from `tokenizer().getToken()`. Note // that you are not allowed to call the parser from the // callback—that will corrupt its internal state. onToken: null, // A function can be passed as `onComment` option, which will // cause Acorn to call that function with `(block, text, start, // end)` parameters whenever a comment is skipped. `block` is a // boolean indicating whether this is a block (`/* */`) comment, // `text` is the content of the comment, and `start` and `end` are // character offsets that denote the start and end of the comment. // When the `locations` option is on, two more parameters are // passed, the full `{line, column}` locations of the start and // end of the comments. Note that you are not allowed to call the // parser from the callback—that will corrupt its internal state. onComment: null, // 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`. // // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 ranges: false, // It is possible to parse multiple files into a single AST by // passing the tree produced by parsing the first file as // `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. program: null, // When `locations` is on, you can pass this to record the source // file in every node's `loc` object. sourceFile: null, // This value, if given, is stored in every node, whether // `locations` is on or off. directSourceFile: null, // When enabled, parenthesized expressions are represented by // (non-standard) ParenthesizedExpression nodes preserveParens: false, plugins: {} } // Interpret and default an options object export function getOptions(opts) { let options = {} for (let opt in defaultOptions) options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt] if (options.ecmaVersion >= 2015) options.ecmaVersion -= 2009 if (options.allowReserved == null) options.allowReserved = options.ecmaVersion < 5 if (isArray(options.onToken)) { let tokens = options.onToken options.onToken = (token) => tokens.push(token) } if (isArray(options.onComment)) options.onComment = pushComment(options, options.onComment) return options } function pushComment(options, array) { return function(block, text, start, end, startLoc, endLoc) { let comment = { type: block ? "Block" : "Line", value: text, start: start, end: end } if (options.locations) comment.loc = new SourceLocation(this, startLoc, endLoc) if (options.ranges) comment.range = [start, end] array.push(comment) } } acorn-5.5.3/src/parseutil.js000066400000000000000000000100761325020065300157630ustar00rootroot00000000000000import {types as tt} from "./tokentype" import {Parser} from "./state" import {lineBreak, skipWhiteSpace} from "./whitespace" const pp = Parser.prototype // ## Parser utilities const literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/ pp.strictDirective = function(start) { for (;;) { skipWhiteSpace.lastIndex = start start += skipWhiteSpace.exec(this.input)[0].length let match = literal.exec(this.input.slice(start)) if (!match) return false if ((match[1] || match[2]) == "use strict") return true start += match[0].length } } // Predicate that tests whether the next token is of the given // type, and if yes, consumes it as a side effect. pp.eat = function(type) { if (this.type === type) { this.next() return true } else { return false } } // Tests whether parsed token is a contextual keyword. pp.isContextual = function(name) { return this.type === tt.name && this.value === name && !this.containsEsc } // Consumes contextual keyword if possible. pp.eatContextual = function(name) { if (!this.isContextual(name)) return false this.next() return true } // Asserts that following token is given contextual keyword. pp.expectContextual = function(name) { if (!this.eatContextual(name)) this.unexpected() } // Test whether a semicolon can be inserted at the current position. pp.canInsertSemicolon = function() { return this.type === tt.eof || this.type === tt.braceR || lineBreak.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.insertSemicolon()) this.unexpected() } pp.afterTrailingComma = function(tokType, notNext) { if (this.type == tokType) { if (this.options.onTrailingComma) this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc) if (!notNext) this.next() return true } } // Expect a token of a given type. If found, consume it, otherwise, // raise an unexpected token error. pp.expect = function(type) { this.eat(type) || this.unexpected() } // Raise an unexpected token error. pp.unexpected = function(pos) { this.raise(pos != null ? pos : this.start, "Unexpected token") } export function DestructuringErrors() { this.shorthandAssign = this.trailingComma = this.parenthesizedAssign = this.parenthesizedBind = this.doubleProto = -1 } pp.checkPatternErrors = function(refDestructuringErrors, isAssign) { if (!refDestructuringErrors) return if (refDestructuringErrors.trailingComma > -1) this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element") let parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind if (parens > -1) this.raiseRecoverable(parens, "Parenthesized pattern") } pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) { if (!refDestructuringErrors) return false let {shorthandAssign, doubleProto} = refDestructuringErrors if (!andThrow) return shorthandAssign >= 0 || doubleProto >= 0 if (shorthandAssign >= 0) this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns") if (doubleProto >= 0) this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property") } pp.checkYieldAwaitInDefaultParams = function() { if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) this.raise(this.yieldPos, "Yield expression cannot be a default value") if (this.awaitPos) this.raise(this.awaitPos, "Await expression cannot be a default value") } pp.isSimpleAssignTarget = function(expr) { if (expr.type === "ParenthesizedExpression") return this.isSimpleAssignTarget(expr.expression) return expr.type === "Identifier" || expr.type === "MemberExpression" } acorn-5.5.3/src/regexp.js000066400000000000000000000705771325020065300152610ustar00rootroot00000000000000import {isIdentifierStart, isIdentifierChar} from "./identifier.js" import {Parser} from "./state.js" import UNICODE_PROPERTY_VALUES from "./unicode-property-data.js" const pp = Parser.prototype export class RegExpValidationState { constructor(parser) { this.parser = parser this.validFlags = `gim${parser.options.ecmaVersion >= 6 ? "uy" : ""}${parser.options.ecmaVersion >= 9 ? "s" : ""}` this.source = "" this.flags = "" this.start = 0 this.switchU = false this.switchN = false this.pos = 0 this.lastIntValue = 0 this.lastStringValue = "" this.lastAssertionIsQuantifiable = false this.numCapturingParens = 0 this.maxBackReference = 0 this.groupNames = [] this.backReferenceNames = [] } reset(start, pattern, flags) { const unicode = flags.indexOf("u") !== -1 this.start = start | 0 this.source = pattern + "" this.flags = flags this.switchU = unicode && this.parser.options.ecmaVersion >= 6 this.switchN = unicode && this.parser.options.ecmaVersion >= 9 } raise(message) { this.parser.raiseRecoverable(this.start, `Invalid regular expression: /${this.source}/: ${message}`) } // If u flag is given, this returns the code point at the index (it combines a surrogate pair). // Otherwise, this returns the code unit of the index (can be a part of a surrogate pair). at(i) { const s = this.source const l = s.length if (i >= l) { return -1 } const c = s.charCodeAt(i) if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { return c } return (c << 10) + s.charCodeAt(i + 1) - 0x35FDC00 } nextIndex(i) { const s = this.source const l = s.length if (i >= l) { return l } const c = s.charCodeAt(i) if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { return i + 1 } return i + 2 } current() { return this.at(this.pos) } lookahead() { return this.at(this.nextIndex(this.pos)) } advance() { this.pos = this.nextIndex(this.pos) } eat(ch) { if (this.current() === ch) { this.advance() return true } return false } } function codePointToString(ch) { if (ch <= 0xFFFF) return String.fromCharCode(ch) ch -= 0x10000 return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00) } /** * Validate the flags part of a given RegExpLiteral. * * @param {RegExpValidationState} state The state to validate RegExp. * @returns {void} */ pp.validateRegExpFlags = function(state) { const validFlags = state.validFlags const flags = state.flags for (let i = 0; i < flags.length; i++) { const flag = flags.charAt(i) if (validFlags.indexOf(flag) == -1) { this.raise(state.start, "Invalid regular expression flag") } if (flags.indexOf(flag, i + 1) > -1) { this.raise(state.start, "Duplicate regular expression flag") } } } /** * Validate the pattern part of a given RegExpLiteral. * * @param {RegExpValidationState} state The state to validate RegExp. * @returns {void} */ pp.validateRegExpPattern = function(state) { this.regexp_pattern(state) // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of // parsing contains a |GroupName|, reparse with the goal symbol // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError* // exception if _P_ did not conform to the grammar, if any elements of _P_ // were not matched by the parse, or if any Early Error conditions exist. if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) { state.switchN = true this.regexp_pattern(state) } } // https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern pp.regexp_pattern = function(state) { state.pos = 0 state.lastIntValue = 0 state.lastStringValue = "" state.lastAssertionIsQuantifiable = false state.numCapturingParens = 0 state.maxBackReference = 0 state.groupNames.length = 0 state.backReferenceNames.length = 0 this.regexp_disjunction(state) if (state.pos !== state.source.length) { // Make the same messages as V8. if (state.eat(0x29 /* ) */)) { state.raise("Unmatched ')'") } if (state.eat(0x5D /* [ */) || state.eat(0x7D /* } */)) { state.raise("Lone quantifier brackets") } } if (state.maxBackReference > state.numCapturingParens) { state.raise("Invalid escape") } for (const name of state.backReferenceNames) { if (state.groupNames.indexOf(name) === -1) { state.raise("Invalid named capture referenced") } } } // https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction pp.regexp_disjunction = function(state) { this.regexp_alternative(state) while (state.eat(0x7C /* | */)) { this.regexp_alternative(state) } // Make the same message as V8. if (this.regexp_eatQuantifier(state, true)) { state.raise("Nothing to repeat") } if (state.eat(0x7B /* { */)) { state.raise("Lone quantifier brackets") } } // https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative pp.regexp_alternative = function(state) { while (state.pos < state.source.length && this.regexp_eatTerm(state)) ; } // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term pp.regexp_eatTerm = function(state) { if (this.regexp_eatAssertion(state)) { // Handle `QuantifiableAssertion Quantifier` alternative. // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion // is a QuantifiableAssertion. if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) { // Make the same message as V8. if (state.switchU) { state.raise("Invalid quantifier") } } return true } if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) { this.regexp_eatQuantifier(state) return true } return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion pp.regexp_eatAssertion = function(state) { const start = state.pos state.lastAssertionIsQuantifiable = false // ^, $ if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) { return true } // \b \B if (state.eat(0x5C /* \ */)) { if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) { return true } state.pos = start } // Lookahead / Lookbehind if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) { let lookbehind = false if (this.options.ecmaVersion >= 9) { lookbehind = state.eat(0x3C /* < */) } if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) { this.regexp_disjunction(state) if (!state.eat(0x29 /* ) */)) { state.raise("Unterminated group") } state.lastAssertionIsQuantifiable = !lookbehind return true } } state.pos = start return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier pp.regexp_eatQuantifier = function(state, noError = false) { if (this.regexp_eatQuantifierPrefix(state, noError)) { state.eat(0x3F /* ? */) return true } return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix pp.regexp_eatQuantifierPrefix = function(state, noError) { return ( state.eat(0x2A /* * */) || state.eat(0x2B /* + */) || state.eat(0x3F /* ? */) || this.regexp_eatBracedQuantifier(state, noError) ) } pp.regexp_eatBracedQuantifier = function(state, noError) { const start = state.pos if (state.eat(0x7B /* { */)) { let min = 0, max = -1 if (this.regexp_eatDecimalDigits(state)) { min = state.lastIntValue if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) { max = state.lastIntValue } if (state.eat(0x7D /* } */)) { // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term if (max !== -1 && max < min && !noError) { state.raise("numbers out of order in {} quantifier") } return true } } if (state.switchU && !noError) { state.raise("Incomplete quantifier") } state.pos = start } return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-Atom pp.regexp_eatAtom = function(state) { return ( this.regexp_eatPatternCharacters(state) || state.eat(0x2E /* . */) || this.regexp_eatReverseSolidusAtomEscape(state) || this.regexp_eatCharacterClass(state) || this.regexp_eatUncapturingGroup(state) || this.regexp_eatCapturingGroup(state) ) } pp.regexp_eatReverseSolidusAtomEscape = function(state) { const start = state.pos if (state.eat(0x5C /* \ */)) { if (this.regexp_eatAtomEscape(state)) { return true } state.pos = start } return false } pp.regexp_eatUncapturingGroup = function(state) { const start = state.pos if (state.eat(0x28 /* ( */)) { if (state.eat(0x3F /* ? */) && state.eat(0x3A /* : */)) { this.regexp_disjunction(state) if (state.eat(0x29 /* ) */)) { return true } state.raise("Unterminated group") } state.pos = start } return false } pp.regexp_eatCapturingGroup = function(state) { if (state.eat(0x28 /* ( */)) { if (this.options.ecmaVersion >= 9) { this.regexp_groupSpecifier(state) } else if (state.current() === 0x3F /* ? */) { state.raise("Invalid group") } this.regexp_disjunction(state) if (state.eat(0x29 /* ) */)) { state.numCapturingParens += 1 return true } state.raise("Unterminated group") } return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom pp.regexp_eatExtendedAtom = function(state) { return ( state.eat(0x2E /* . */) || this.regexp_eatReverseSolidusAtomEscape(state) || this.regexp_eatCharacterClass(state) || this.regexp_eatUncapturingGroup(state) || this.regexp_eatCapturingGroup(state) || this.regexp_eatInvalidBracedQuantifier(state) || this.regexp_eatExtendedPatternCharacter(state) ) } // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier pp.regexp_eatInvalidBracedQuantifier = function(state) { if (this.regexp_eatBracedQuantifier(state, true)) { state.raise("Nothing to repeat") } return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter pp.regexp_eatSyntaxCharacter = function(state) { const ch = state.current() if (isSyntaxCharacter(ch)) { state.lastIntValue = ch state.advance() return true } return false } function isSyntaxCharacter(ch) { return ( ch === 0x24 /* $ */ || ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ || ch === 0x2E /* . */ || ch === 0x3F /* ? */ || ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ || ch >= 0x7B /* { */ && ch <= 0x7D /* } */ ) } // https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter // But eat eager. pp.regexp_eatPatternCharacters = function(state) { const start = state.pos let ch = 0 while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) { state.advance() } return state.pos !== start } // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter pp.regexp_eatExtendedPatternCharacter = function(state) { const ch = state.current() if ( ch !== -1 && ch !== 0x24 /* $ */ && !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) && ch !== 0x2E /* . */ && ch !== 0x3F /* ? */ && ch !== 0x5B /* [ */ && ch !== 0x5E /* ^ */ && ch !== 0x7C /* | */ ) { state.advance() return true } return false } // GroupSpecifier[U] :: // [empty] // `?` GroupName[?U] pp.regexp_groupSpecifier = function(state) { if (state.eat(0x3F /* ? */)) { if (this.regexp_eatGroupName(state)) { if (state.groupNames.indexOf(state.lastStringValue) !== -1) { state.raise("Duplicate capture group name") } state.groupNames.push(state.lastStringValue) return } state.raise("Invalid group") } } // GroupName[U] :: // `<` RegExpIdentifierName[?U] `>` // Note: this updates `state.lastStringValue` property with the eaten name. pp.regexp_eatGroupName = function(state) { state.lastStringValue = "" if (state.eat(0x3C /* < */)) { if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) { return true } state.raise("Invalid capture group name") } return false } // RegExpIdentifierName[U] :: // RegExpIdentifierStart[?U] // RegExpIdentifierName[?U] RegExpIdentifierPart[?U] // Note: this updates `state.lastStringValue` property with the eaten name. pp.regexp_eatRegExpIdentifierName = function(state) { state.lastStringValue = "" if (this.regexp_eatRegExpIdentifierStart(state)) { state.lastStringValue += codePointToString(state.lastIntValue) while (this.regexp_eatRegExpIdentifierPart(state)) { state.lastStringValue += codePointToString(state.lastIntValue) } return true } return false } // RegExpIdentifierStart[U] :: // UnicodeIDStart // `$` // `_` // `\` RegExpUnicodeEscapeSequence[?U] pp.regexp_eatRegExpIdentifierStart = function(state) { const start = state.pos let ch = state.current() state.advance() if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) { ch = state.lastIntValue } if (isRegExpIdentifierStart(ch)) { state.lastIntValue = ch return true } state.pos = start return false } function isRegExpIdentifierStart(ch) { return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ } // RegExpIdentifierPart[U] :: // UnicodeIDContinue // `$` // `_` // `\` RegExpUnicodeEscapeSequence[?U] // // pp.regexp_eatRegExpIdentifierPart = function(state) { const start = state.pos let ch = state.current() state.advance() if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) { ch = state.lastIntValue } if (isRegExpIdentifierPart(ch)) { state.lastIntValue = ch return true } state.pos = start return false } function isRegExpIdentifierPart(ch) { return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* */ || ch === 0x200D /* */ } // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape pp.regexp_eatAtomEscape = function(state) { if ( this.regexp_eatBackReference(state) || this.regexp_eatCharacterClassEscape(state) || this.regexp_eatCharacterEscape(state) || (state.switchN && this.regexp_eatKGroupName(state)) ) { return true } if (state.switchU) { // Make the same message as V8. if (state.current() === 0x63 /* c */) { state.raise("Invalid unicode escape") } state.raise("Invalid escape") } return false } pp.regexp_eatBackReference = function(state) { const start = state.pos if (this.regexp_eatDecimalEscape(state)) { const n = state.lastIntValue if (state.switchU) { // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape if (n > state.maxBackReference) { state.maxBackReference = n } return true } if (n <= state.numCapturingParens) { return true } state.pos = start } return false } pp.regexp_eatKGroupName = function(state) { if (state.eat(0x6B /* k */)) { if (this.regexp_eatGroupName(state)) { state.backReferenceNames.push(state.lastStringValue) return true } state.raise("Invalid named reference") } return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape pp.regexp_eatCharacterEscape = function(state) { return ( this.regexp_eatControlEscape(state) || this.regexp_eatCControlLetter(state) || this.regexp_eatZero(state) || this.regexp_eatHexEscapeSequence(state) || this.regexp_eatRegExpUnicodeEscapeSequence(state) || (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) || this.regexp_eatIdentityEscape(state) ) } pp.regexp_eatCControlLetter = function(state) { const start = state.pos if (state.eat(0x63 /* c */)) { if (this.regexp_eatControlLetter(state)) { return true } state.pos = start } return false } pp.regexp_eatZero = function(state) { if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) { state.lastIntValue = 0 state.advance() return true } return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape pp.regexp_eatControlEscape = function(state) { const ch = state.current() if (ch === 0x74 /* t */) { state.lastIntValue = 0x09 /* \t */ state.advance() return true } if (ch === 0x6E /* n */) { state.lastIntValue = 0x0A /* \n */ state.advance() return true } if (ch === 0x76 /* v */) { state.lastIntValue = 0x0B /* \v */ state.advance() return true } if (ch === 0x66 /* f */) { state.lastIntValue = 0x0C /* \f */ state.advance() return true } if (ch === 0x72 /* r */) { state.lastIntValue = 0x0D /* \r */ state.advance() return true } return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter pp.regexp_eatControlLetter = function(state) { const ch = state.current() if (isControlLetter(ch)) { state.lastIntValue = ch % 0x20 state.advance() return true } return false } function isControlLetter(ch) { return ( (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) || (ch >= 0x61 /* a */ && ch <= 0x7A /* z */) ) } // https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence pp.regexp_eatRegExpUnicodeEscapeSequence = function(state) { const start = state.pos if (state.eat(0x75 /* u */)) { if (this.regexp_eatFixedHexDigits(state, 4)) { const lead = state.lastIntValue if (state.switchU && lead >= 0xD800 && lead <= 0xDBFF) { const leadSurrogateEnd = state.pos if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) { const trail = state.lastIntValue if (trail >= 0xDC00 && trail <= 0xDFFF) { state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000 return true } } state.pos = leadSurrogateEnd state.lastIntValue = lead } return true } if ( state.switchU && state.eat(0x7B /* { */) && this.regexp_eatHexDigits(state) && state.eat(0x7D /* } */) && isValidUnicode(state.lastIntValue) ) { return true } if (state.switchU) { state.raise("Invalid unicode escape") } state.pos = start } return false } function isValidUnicode(ch) { return ch >= 0 && ch <= 0x10FFFF } // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape pp.regexp_eatIdentityEscape = function(state) { if (state.switchU) { if (this.regexp_eatSyntaxCharacter(state)) { return true } if (state.eat(0x2F /* / */)) { state.lastIntValue = 0x2F /* / */ return true } return false } const ch = state.current() if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) { state.lastIntValue = ch state.advance() return true } return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape pp.regexp_eatDecimalEscape = function(state) { state.lastIntValue = 0 let ch = state.current() if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) { do { state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */) state.advance() } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) return true } return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape pp.regexp_eatCharacterClassEscape = function(state) { const ch = state.current() if (isCharacterClassEscape(ch)) { state.lastIntValue = -1 state.advance() return true } if ( state.switchU && this.options.ecmaVersion >= 9 && (ch === 0x50 /* P */ || ch === 0x70 /* p */) ) { state.lastIntValue = -1 state.advance() if ( state.eat(0x7B /* { */) && this.regexp_eatUnicodePropertyValueExpression(state) && state.eat(0x7D /* } */) ) { return true } state.raise("Invalid property name") } return false } function isCharacterClassEscape(ch) { return ( ch === 0x64 /* d */ || ch === 0x44 /* D */ || ch === 0x73 /* s */ || ch === 0x53 /* S */ || ch === 0x77 /* w */ || ch === 0x57 /* W */ ) } // UnicodePropertyValueExpression :: // UnicodePropertyName `=` UnicodePropertyValue // LoneUnicodePropertyNameOrValue pp.regexp_eatUnicodePropertyValueExpression = function(state) { const start = state.pos // UnicodePropertyName `=` UnicodePropertyValue if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) { const name = state.lastStringValue if (this.regexp_eatUnicodePropertyValue(state)) { const value = state.lastStringValue this.regexp_validateUnicodePropertyNameAndValue(state, name, value) return true } } state.pos = start // LoneUnicodePropertyNameOrValue if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) { const nameOrValue = state.lastStringValue this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue) return true } return false } pp.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) { if (!UNICODE_PROPERTY_VALUES.hasOwnProperty(name) || UNICODE_PROPERTY_VALUES[name].indexOf(value) === -1) { state.raise("Invalid property name") } } pp.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) { if (UNICODE_PROPERTY_VALUES.$LONE.indexOf(nameOrValue) === -1) { state.raise("Invalid property name") } } // UnicodePropertyName :: // UnicodePropertyNameCharacters pp.regexp_eatUnicodePropertyName = function(state) { let ch = 0 state.lastStringValue = "" while (isUnicodePropertyNameCharacter(ch = state.current())) { state.lastStringValue += codePointToString(ch) state.advance() } return state.lastStringValue !== "" } function isUnicodePropertyNameCharacter(ch) { return isControlLetter(ch) || ch === 0x5F /* _ */ } // UnicodePropertyValue :: // UnicodePropertyValueCharacters pp.regexp_eatUnicodePropertyValue = function(state) { let ch = 0 state.lastStringValue = "" while (isUnicodePropertyValueCharacter(ch = state.current())) { state.lastStringValue += codePointToString(ch) state.advance() } return state.lastStringValue !== "" } function isUnicodePropertyValueCharacter(ch) { return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch) } // LoneUnicodePropertyNameOrValue :: // UnicodePropertyValueCharacters pp.regexp_eatLoneUnicodePropertyNameOrValue = function(state) { return this.regexp_eatUnicodePropertyValue(state) } // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass pp.regexp_eatCharacterClass = function(state) { if (state.eat(0x5B /* [ */)) { state.eat(0x5E /* ^ */) this.regexp_classRanges(state) if (state.eat(0x5D /* [ */)) { return true } // Unreachable since it threw "unterminated regular expression" error before. state.raise("Unterminated character class") } return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash pp.regexp_classRanges = function(state) { while (this.regexp_eatClassAtom(state)) { const left = state.lastIntValue if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) { const right = state.lastIntValue if (state.switchU && (left === -1 || right === -1)) { state.raise("Invalid character class") } if (left !== -1 && right !== -1 && left > right) { state.raise("Range out of order in character class") } } } } // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash pp.regexp_eatClassAtom = function(state) { const start = state.pos if (state.eat(0x5C /* \ */)) { if (this.regexp_eatClassEscape(state)) { return true } if (state.switchU) { // Make the same message as V8. const ch = state.current() if (ch === 0x63 /* c */ || isOctalDigit(ch)) { state.raise("Invalid class escape") } state.raise("Invalid escape") } state.pos = start } const ch = state.current() if (ch !== 0x5D /* [ */) { state.lastIntValue = ch state.advance() return true } return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape pp.regexp_eatClassEscape = function(state) { const start = state.pos if (state.eat(0x62 /* b */)) { state.lastIntValue = 0x08 /* */ return true } if (state.switchU && state.eat(0x2D /* - */)) { state.lastIntValue = 0x2D /* - */ return true } if (!state.switchU && state.eat(0x63 /* c */)) { if (this.regexp_eatClassControlLetter(state)) { return true } state.pos = start } return ( this.regexp_eatCharacterClassEscape(state) || this.regexp_eatCharacterEscape(state) ) } // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter pp.regexp_eatClassControlLetter = function(state) { const ch = state.current() if (isDecimalDigit(ch) || ch === 0x5F /* _ */) { state.lastIntValue = ch % 0x20 state.advance() return true } return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence pp.regexp_eatHexEscapeSequence = function(state) { const start = state.pos if (state.eat(0x78 /* x */)) { if (this.regexp_eatFixedHexDigits(state, 2)) { return true } if (state.switchU) { state.raise("Invalid escape") } state.pos = start } return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits pp.regexp_eatDecimalDigits = function(state) { const start = state.pos let ch = 0 state.lastIntValue = 0 while (isDecimalDigit(ch = state.current())) { state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */) state.advance() } return state.pos !== start } function isDecimalDigit(ch) { return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */ } // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits pp.regexp_eatHexDigits = function(state) { const start = state.pos let ch = 0 state.lastIntValue = 0 while (isHexDigit(ch = state.current())) { state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch) state.advance() } return state.pos !== start } function isHexDigit(ch) { return ( (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) || (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) || (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) ) } function hexToInt(ch) { if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) { return 10 + (ch - 0x41 /* A */) } if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) { return 10 + (ch - 0x61 /* a */) } return ch - 0x30 /* 0 */ } // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence // Allows only 0-377(octal) i.e. 0-255(decimal). pp.regexp_eatLegacyOctalEscapeSequence = function(state) { if (this.regexp_eatOctalDigit(state)) { const n1 = state.lastIntValue if (this.regexp_eatOctalDigit(state)) { const n2 = state.lastIntValue if (n1 <= 3 && this.regexp_eatOctalDigit(state)) { state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue } else { state.lastIntValue = n1 * 8 + n2 } } else { state.lastIntValue = n1 } return true } return false } // https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit pp.regexp_eatOctalDigit = function(state) { const ch = state.current() if (isOctalDigit(ch)) { state.lastIntValue = ch - 0x30 /* 0 */ state.advance() return true } state.lastIntValue = 0 return false } function isOctalDigit(ch) { return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */ } // https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit // And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence pp.regexp_eatFixedHexDigits = function(state, length) { const start = state.pos state.lastIntValue = 0 for (let i = 0; i < length; ++i) { const ch = state.current() if (!isHexDigit(ch)) { state.pos = start return false } state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch) state.advance() } return true } acorn-5.5.3/src/scope.js000066400000000000000000000052561325020065300150700ustar00rootroot00000000000000import {Parser} from "./state" import {has} from "./util" const pp = Parser.prototype // Object.assign polyfill const assign = Object.assign || function(target, ...sources) { for (let source of sources) { for (const key in source) { if (has(source, key)) { target[key] = source[key] } } } return target } // The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. pp.enterFunctionScope = function() { // var: a hash of var-declared names in the current lexical scope // lexical: a hash of lexically-declared names in the current lexical scope // childVar: a hash of var-declared names in all child lexical scopes of the current lexical scope (within the current function scope) // parentLexical: a hash of lexically-declared names in all parent lexical scopes of the current lexical scope (within the current function scope) this.scopeStack.push({var: {}, lexical: {}, childVar: {}, parentLexical: {}}) } pp.exitFunctionScope = function() { this.scopeStack.pop() } pp.enterLexicalScope = function() { const parentScope = this.scopeStack[this.scopeStack.length - 1] const childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}} this.scopeStack.push(childScope) assign(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical) } pp.exitLexicalScope = function() { const childScope = this.scopeStack.pop() const parentScope = this.scopeStack[this.scopeStack.length - 1] assign(parentScope.childVar, childScope.var, childScope.childVar) } /** * A name can be declared with `var` if there are no variables with the same name declared with `let`/`const` * in the current lexical scope or any of the parent lexical scopes in this function. */ pp.canDeclareVarName = function(name) { const currentScope = this.scopeStack[this.scopeStack.length - 1] return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name) } /** * A name can be declared with `let`/`const` if there are no variables with the same name declared with `let`/`const` * in the current scope, and there are no variables with the same name declared with `var` in the current scope or in * any child lexical scopes in this function. */ pp.canDeclareLexicalName = function(name) { const currentScope = this.scopeStack[this.scopeStack.length - 1] return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name) } pp.declareVarName = function(name) { this.scopeStack[this.scopeStack.length - 1].var[name] = true } pp.declareLexicalName = function(name) { this.scopeStack[this.scopeStack.length - 1].lexical[name] = true } acorn-5.5.3/src/state.js000066400000000000000000000077301325020065300150760ustar00rootroot00000000000000import {reservedWords, keywords} from "./identifier" import {types as tt} from "./tokentype" import {lineBreak} from "./whitespace" import {getOptions} from "./options" // Registered plugins export const plugins = {} function keywordRegexp(words) { return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$") } export class Parser { constructor(options, input, startPos) { this.options = options = getOptions(options) this.sourceFile = options.sourceFile this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]) let reserved = "" if (!options.allowReserved) { for (let v = options.ecmaVersion;; v--) if (reserved = reservedWords[v]) break if (options.sourceType == "module") reserved += " await" } this.reservedWords = keywordRegexp(reserved) let reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict this.reservedWordsStrict = keywordRegexp(reservedStrict) this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind) this.input = String(input) // Used to signal to callers of `readWord1` whether the word // contained any escape sequences. This is needed because words with // escape sequences must not be interpreted as keywords. this.containsEsc = false // Load plugins this.loadPlugins(options.plugins) // Set up token state // The current position of the tokenizer in the input. if (startPos) { this.pos = startPos this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1 this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length } else { this.pos = this.lineStart = 0 this.curLine = 1 } // Properties of the current token: // Its type this.type = tt.eof // For tokens that include more information than their type, the value this.value = null // Its start and end offset this.start = this.end = this.pos // And, if locations are used, the {line, column} object // corresponding to those offsets this.startLoc = this.endLoc = this.curPosition() // Position information for the previous token this.lastTokEndLoc = this.lastTokStartLoc = null this.lastTokStart = this.lastTokEnd = this.pos // The context stack is used to superficially track syntactic // context to predict whether a regular expression is allowed in a // given position. this.context = this.initialContext() this.exprAllowed = true // Figure out if it's a module code. this.inModule = options.sourceType === "module" this.strict = this.inModule || this.strictDirective(this.pos) // Used to signify the start of a potential arrow function this.potentialArrowAt = -1 // Flags to track whether we are in a function, a generator, an async function. this.inFunction = this.inGenerator = this.inAsync = false // Positions to delayed-check that yield/await does not exist in default parameters. this.yieldPos = this.awaitPos = 0 // Labels in scope. this.labels = [] // If enabled, skip leading hashbang line. if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") this.skipLineComment(2) // Scope tracking for duplicate variable names (see scope.js) this.scopeStack = [] this.enterFunctionScope() // For RegExp validation this.regexpState = null } // DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them isKeyword(word) { return this.keywords.test(word) } isReservedWord(word) { return this.reservedWords.test(word) } extend(name, f) { this[name] = f(this[name]) } loadPlugins(pluginConfigs) { for (let name in pluginConfigs) { let plugin = plugins[name] if (!plugin) throw new Error("Plugin '" + name + "' not found") plugin(this, pluginConfigs[name]) } } parse() { let node = this.options.program || this.startNode() this.nextToken() return this.parseTopLevel(node) } } acorn-5.5.3/src/statement.js000066400000000000000000000670071325020065300157650ustar00rootroot00000000000000import {types as tt} from "./tokentype" import {Parser} from "./state" import {lineBreak, skipWhiteSpace} from "./whitespace" import {isIdentifierStart, isIdentifierChar, keywordRelationalOperator} from "./identifier" import {has} from "./util" import {DestructuringErrors} from "./parseutil" const pp = Parser.prototype // ### Statement parsing // Parse a program. Initializes the parser, reads any number of // statements, and wraps them in a Program node. Optionally takes a // `program` argument. If present, the statements will be appended // to its body instead of creating a new node. pp.parseTopLevel = function(node) { let exports = {} if (!node.body) node.body = [] while (this.type !== tt.eof) { let stmt = this.parseStatement(true, true, exports) node.body.push(stmt) } this.adaptDirectivePrologue(node.body) this.next() if (this.options.ecmaVersion >= 6) { node.sourceType = this.options.sourceType } return this.finishNode(node, "Program") } const loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"} pp.isLet = function() { if (this.options.ecmaVersion < 6 || !this.isContextual("let")) return false skipWhiteSpace.lastIndex = this.pos let skip = skipWhiteSpace.exec(this.input) let next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next) if (nextCh === 91 || nextCh == 123) return true // '{' and '[' if (isIdentifierStart(nextCh, true)) { let pos = next + 1 while (isIdentifierChar(this.input.charCodeAt(pos), true)) ++pos let ident = this.input.slice(next, pos) if (!keywordRelationalOperator.test(ident)) return true } return false } // check 'async [no LineTerminator here] function' // - 'async /*foo*/ function' is OK. // - 'async /*\n*/ function' is invalid. pp.isAsyncFunction = function() { if (this.options.ecmaVersion < 8 || !this.isContextual("async")) return false skipWhiteSpace.lastIndex = this.pos let skip = skipWhiteSpace.exec(this.input) let next = this.pos + skip[0].length return !lineBreak.test(this.input.slice(this.pos, next)) && this.input.slice(next, next + 8) === "function" && (next + 8 == this.input.length || !isIdentifierChar(this.input.charAt(next + 8))) } // Parse a single statement. // // If expecting a statement and finding a slash operator, parse a // regular expression literal. This is to handle cases like // `if (foo) /blah/.exec(foo)`, where looking at the previous token // does not help. pp.parseStatement = function(declaration, topLevel, exports) { let starttype = this.type, node = this.startNode(), kind if (this.isLet()) { starttype = tt._var kind = "let" } // Most types of statements are recognized by the keyword they // start with. Many are trivial to parse, some require a bit of // complexity. switch (starttype) { case tt._break: case tt._continue: return this.parseBreakContinueStatement(node, starttype.keyword) case tt._debugger: return this.parseDebuggerStatement(node) case tt._do: return this.parseDoStatement(node) case tt._for: return this.parseForStatement(node) case tt._function: if (!declaration && this.options.ecmaVersion >= 6) this.unexpected() return this.parseFunctionStatement(node, false) case tt._class: if (!declaration) this.unexpected() return this.parseClass(node, true) case tt._if: return this.parseIfStatement(node) case tt._return: return this.parseReturnStatement(node) case tt._switch: return this.parseSwitchStatement(node) case tt._throw: return this.parseThrowStatement(node) case tt._try: return this.parseTryStatement(node) case tt._const: case tt._var: kind = kind || this.value if (!declaration && kind != "var") this.unexpected() return this.parseVarStatement(node, kind) case tt._while: return this.parseWhileStatement(node) case tt._with: return this.parseWithStatement(node) case tt.braceL: return this.parseBlock() case tt.semi: return this.parseEmptyStatement(node) case tt._export: case tt._import: if (!this.options.allowImportExportEverywhere) { if (!topLevel) this.raise(this.start, "'import' and 'export' may only appear at the top level") if (!this.inModule) this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'") } return starttype === tt._import ? this.parseImport(node) : this.parseExport(node, exports) // If the statement does not start with a statement keyword or a // brace, it's an ExpressionStatement or LabeledStatement. We // simply start parsing an expression, and afterwards, if the // next token is a colon and the expression was a simple // Identifier node, we switch to interpreting it as a label. default: if (this.isAsyncFunction()) { if (!declaration) this.unexpected() this.next() return this.parseFunctionStatement(node, true) } let maybeName = this.value, expr = this.parseExpression() if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon)) return this.parseLabeledStatement(node, maybeName, expr) else return this.parseExpressionStatement(node, expr) } } pp.parseBreakContinueStatement = function(node, keyword) { let isBreak = keyword == "break" this.next() if (this.eat(tt.semi) || this.insertSemicolon()) node.label = null else if (this.type !== tt.name) this.unexpected() else { node.label = this.parseIdent() this.semicolon() } // Verify that there is an actual destination to break or // continue to. let i = 0 for (; i < this.labels.length; ++i) { let lab = this.labels[i] if (node.label == null || lab.name === node.label.name) { if (lab.kind != null && (isBreak || lab.kind === "loop")) break if (node.label && isBreak) break } } if (i === this.labels.length) this.raise(node.start, "Unsyntactic " + keyword) return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") } pp.parseDebuggerStatement = function(node) { this.next() this.semicolon() return this.finishNode(node, "DebuggerStatement") } pp.parseDoStatement = function(node) { this.next() this.labels.push(loopLabel) node.body = this.parseStatement(false) this.labels.pop() this.expect(tt._while) node.test = this.parseParenExpression() if (this.options.ecmaVersion >= 6) this.eat(tt.semi) else this.semicolon() return this.finishNode(node, "DoWhileStatement") } // Disambiguating between a `for` and a `for`/`in` or `for`/`of` // loop is non-trivial. Basically, we have to parse the init `var` // statement or expression, disallowing the `in` operator (see // the second parameter to `parseExpression`), and then check // whether the next token is `in` or `of`. When there is no init // part (semicolon immediately after the opening parenthesis), it // is a regular `for` loop. pp.parseForStatement = function(node) { this.next() let awaitAt = (this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await")) ? this.lastTokStart : -1 this.labels.push(loopLabel) this.enterLexicalScope() this.expect(tt.parenL) if (this.type === tt.semi) { if (awaitAt > -1) this.unexpected(awaitAt) return this.parseFor(node, null) } let isLet = this.isLet() if (this.type === tt._var || this.type === tt._const || isLet) { let init = this.startNode(), kind = isLet ? "let" : this.value this.next() this.parseVar(init, true, kind) this.finishNode(init, "VariableDeclaration") if ((this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init.declarations.length === 1 && !(kind !== "var" && init.declarations[0].init)) { if (this.options.ecmaVersion >= 9) { if (this.type === tt._in) { if (awaitAt > -1) this.unexpected(awaitAt) } else node.await = awaitAt > -1 } return this.parseForIn(node, init) } if (awaitAt > -1) this.unexpected(awaitAt) return this.parseFor(node, init) } let refDestructuringErrors = new DestructuringErrors let init = this.parseExpression(true, refDestructuringErrors) if (this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) { if (this.options.ecmaVersion >= 9) { if (this.type === tt._in) { if (awaitAt > -1) this.unexpected(awaitAt) } else node.await = awaitAt > -1 } this.toAssignable(init, false, refDestructuringErrors) this.checkLVal(init) return this.parseForIn(node, init) } else { this.checkExpressionErrors(refDestructuringErrors, true) } if (awaitAt > -1) this.unexpected(awaitAt) return this.parseFor(node, init) } pp.parseFunctionStatement = function(node, isAsync) { this.next() return this.parseFunction(node, true, false, isAsync) } pp.parseIfStatement = function(node) { this.next() node.test = this.parseParenExpression() // allow function declarations in branches, but only in non-strict mode node.consequent = this.parseStatement(!this.strict && this.type == tt._function) node.alternate = this.eat(tt._else) ? this.parseStatement(!this.strict && this.type == tt._function) : null return this.finishNode(node, "IfStatement") } pp.parseReturnStatement = function(node) { if (!this.inFunction && !this.options.allowReturnOutsideFunction) this.raise(this.start, "'return' outside of function") this.next() // In `return` (and `break`/`continue`), the keywords with // optional arguments, we eagerly look for a semicolon or the // possibility to insert one. if (this.eat(tt.semi) || this.insertSemicolon()) node.argument = null else { node.argument = this.parseExpression(); this.semicolon() } return this.finishNode(node, "ReturnStatement") } pp.parseSwitchStatement = function(node) { this.next() node.discriminant = this.parseParenExpression() node.cases = [] this.expect(tt.braceL) this.labels.push(switchLabel) this.enterLexicalScope() // Statements under must be grouped (by label) in SwitchCase // nodes. `cur` is used to keep the node that we are currently // adding statements to. let cur for (let sawDefault = false; this.type != tt.braceR;) { if (this.type === tt._case || this.type === tt._default) { let isCase = this.type === tt._case if (cur) this.finishNode(cur, "SwitchCase") node.cases.push(cur = this.startNode()) cur.consequent = [] this.next() if (isCase) { cur.test = this.parseExpression() } else { if (sawDefault) this.raiseRecoverable(this.lastTokStart, "Multiple default clauses") sawDefault = true cur.test = null } this.expect(tt.colon) } else { if (!cur) this.unexpected() cur.consequent.push(this.parseStatement(true)) } } this.exitLexicalScope() if (cur) this.finishNode(cur, "SwitchCase") this.next() // Closing brace this.labels.pop() return this.finishNode(node, "SwitchStatement") } pp.parseThrowStatement = function(node) { this.next() if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) this.raise(this.lastTokEnd, "Illegal newline after throw") node.argument = this.parseExpression() this.semicolon() return this.finishNode(node, "ThrowStatement") } // Reused empty array added for node fields that are always empty. const empty = [] pp.parseTryStatement = function(node) { this.next() node.block = this.parseBlock() node.handler = null if (this.type === tt._catch) { let clause = this.startNode() this.next() this.expect(tt.parenL) clause.param = this.parseBindingAtom() this.enterLexicalScope() this.checkLVal(clause.param, "let") this.expect(tt.parenR) clause.body = this.parseBlock(false) this.exitLexicalScope() node.handler = this.finishNode(clause, "CatchClause") } node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null if (!node.handler && !node.finalizer) this.raise(node.start, "Missing catch or finally clause") return this.finishNode(node, "TryStatement") } pp.parseVarStatement = function(node, kind) { this.next() this.parseVar(node, false, kind) this.semicolon() return this.finishNode(node, "VariableDeclaration") } pp.parseWhileStatement = function(node) { this.next() node.test = this.parseParenExpression() this.labels.push(loopLabel) node.body = this.parseStatement(false) this.labels.pop() return this.finishNode(node, "WhileStatement") } pp.parseWithStatement = function(node) { if (this.strict) this.raise(this.start, "'with' in strict mode") this.next() node.object = this.parseParenExpression() node.body = this.parseStatement(false) return this.finishNode(node, "WithStatement") } pp.parseEmptyStatement = function(node) { this.next() return this.finishNode(node, "EmptyStatement") } pp.parseLabeledStatement = function(node, maybeName, expr) { for (let label of this.labels) if (label.name === maybeName) this.raise(expr.start, "Label '" + maybeName + "' is already declared") let kind = this.type.isLoop ? "loop" : this.type === tt._switch ? "switch" : null for (let i = this.labels.length - 1; i >= 0; i--) { let label = this.labels[i] if (label.statementStart == node.start) { // Update information about previous labels on this node label.statementStart = this.start label.kind = kind } else break } this.labels.push({name: maybeName, kind, statementStart: this.start}) node.body = this.parseStatement(true) if (node.body.type == "ClassDeclaration" || node.body.type == "VariableDeclaration" && node.body.kind != "var" || node.body.type == "FunctionDeclaration" && (this.strict || node.body.generator)) this.raiseRecoverable(node.body.start, "Invalid labeled declaration") this.labels.pop() node.label = expr return this.finishNode(node, "LabeledStatement") } pp.parseExpressionStatement = function(node, expr) { node.expression = expr this.semicolon() return this.finishNode(node, "ExpressionStatement") } // Parse a semicolon-enclosed block of statements, handling `"use // strict"` declarations when `allowStrict` is true (used for // function bodies). pp.parseBlock = function(createNewLexicalScope = true) { let node = this.startNode() node.body = [] this.expect(tt.braceL) if (createNewLexicalScope) { this.enterLexicalScope() } while (!this.eat(tt.braceR)) { let stmt = this.parseStatement(true) node.body.push(stmt) } if (createNewLexicalScope) { this.exitLexicalScope() } return this.finishNode(node, "BlockStatement") } // Parse a regular `for` loop. The disambiguation code in // `parseStatement` will already have parsed the init statement or // expression. pp.parseFor = function(node, init) { node.init = init this.expect(tt.semi) node.test = this.type === tt.semi ? null : this.parseExpression() this.expect(tt.semi) node.update = this.type === tt.parenR ? null : this.parseExpression() this.expect(tt.parenR) this.exitLexicalScope() node.body = this.parseStatement(false) this.labels.pop() return this.finishNode(node, "ForStatement") } // Parse a `for`/`in` and `for`/`of` loop, which are almost // same from parser's perspective. pp.parseForIn = function(node, init) { let type = this.type === tt._in ? "ForInStatement" : "ForOfStatement" this.next() if (type == "ForInStatement") { if (init.type === "AssignmentPattern" || (init.type === "VariableDeclaration" && init.declarations[0].init != null && (this.strict || init.declarations[0].id.type !== "Identifier"))) this.raise(init.start, "Invalid assignment in for-in loop head") } node.left = init node.right = type == "ForInStatement" ? this.parseExpression() : this.parseMaybeAssign() this.expect(tt.parenR) this.exitLexicalScope() node.body = this.parseStatement(false) this.labels.pop() return this.finishNode(node, type) } // Parse a list of variable declarations. pp.parseVar = function(node, isFor, kind) { node.declarations = [] node.kind = kind for (;;) { let decl = this.startNode() this.parseVarId(decl, kind) if (this.eat(tt.eq)) { decl.init = this.parseMaybeAssign(isFor) } else if (kind === "const" && !(this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) { this.unexpected() } else if (decl.id.type != "Identifier" && !(isFor && (this.type === tt._in || this.isContextual("of")))) { this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value") } else { decl.init = null } node.declarations.push(this.finishNode(decl, "VariableDeclarator")) if (!this.eat(tt.comma)) break } return node } pp.parseVarId = function(decl, kind) { decl.id = this.parseBindingAtom(kind) this.checkLVal(decl.id, kind, false) } // Parse a function declaration or literal (depending on the // `isStatement` parameter). pp.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) { this.initFunction(node) if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) node.generator = this.eat(tt.star) if (this.options.ecmaVersion >= 8) node.async = !!isAsync if (isStatement) { node.id = isStatement === "nullableID" && this.type != tt.name ? null : this.parseIdent() if (node.id) { this.checkLVal(node.id, "var") } } let oldInGen = this.inGenerator, oldInAsync = this.inAsync, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction this.inGenerator = node.generator this.inAsync = node.async this.yieldPos = 0 this.awaitPos = 0 this.inFunction = true this.enterFunctionScope() if (!isStatement) node.id = this.type == tt.name ? this.parseIdent() : null this.parseFunctionParams(node) this.parseFunctionBody(node, allowExpressionBody) this.inGenerator = oldInGen this.inAsync = oldInAsync this.yieldPos = oldYieldPos this.awaitPos = oldAwaitPos this.inFunction = oldInFunc return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") } pp.parseFunctionParams = function(node) { this.expect(tt.parenL) node.params = this.parseBindingList(tt.parenR, false, this.options.ecmaVersion >= 8) this.checkYieldAwaitInDefaultParams() } // Parse a class declaration or literal (depending on the // `isStatement` parameter). pp.parseClass = function(node, isStatement) { this.next() this.parseClassId(node, isStatement) this.parseClassSuper(node) let classBody = this.startNode() let hadConstructor = false classBody.body = [] this.expect(tt.braceL) while (!this.eat(tt.braceR)) { const member = this.parseClassMember(classBody) if (member && member.type === "MethodDefinition" && member.kind === "constructor") { if (hadConstructor) this.raise(member.start, "Duplicate constructor in the same class") hadConstructor = true } } node.body = this.finishNode(classBody, "ClassBody") return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") } pp.parseClassMember = function(classBody) { if (this.eat(tt.semi)) return null let method = this.startNode() const tryContextual = (k, noLineBreak = false) => { const start = this.start, startLoc = this.startLoc if (!this.eatContextual(k)) return false if (this.type !== tt.parenL && (!noLineBreak || !this.canInsertSemicolon())) return true if (method.key) this.unexpected() method.computed = false method.key = this.startNodeAt(start, startLoc) method.key.name = k this.finishNode(method.key, "Identifier") return false } method.kind = "method" method.static = tryContextual("static") let isGenerator = this.eat(tt.star) let isAsync = false if (!isGenerator) { if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) { isAsync = true isGenerator = this.options.ecmaVersion >= 9 && this.eat(tt.star) } else if (tryContextual("get")) { method.kind = "get" } else if (tryContextual("set")) { method.kind = "set" } } if (!method.key) this.parsePropertyName(method) let {key} = method if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" || key.type === "Literal" && key.value === "constructor")) { if (method.kind !== "method") this.raise(key.start, "Constructor can't have get/set modifier") if (isGenerator) this.raise(key.start, "Constructor can't be a generator") if (isAsync) this.raise(key.start, "Constructor can't be an async method") method.kind = "constructor" } else if (method.static && key.type === "Identifier" && key.name === "prototype") { this.raise(key.start, "Classes may not have a static property named prototype") } this.parseClassMethod(classBody, method, isGenerator, isAsync) if (method.kind === "get" && method.value.params.length !== 0) this.raiseRecoverable(method.value.start, "getter should have no params") if (method.kind === "set" && method.value.params.length !== 1) this.raiseRecoverable(method.value.start, "setter should have exactly one param") if (method.kind === "set" && method.value.params[0].type === "RestElement") this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params") return method } pp.parseClassMethod = function(classBody, method, isGenerator, isAsync) { method.value = this.parseMethod(isGenerator, isAsync) classBody.body.push(this.finishNode(method, "MethodDefinition")) } pp.parseClassId = function(node, isStatement) { node.id = this.type === tt.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null } pp.parseClassSuper = function(node) { node.superClass = this.eat(tt._extends) ? this.parseExprSubscripts() : null } // Parses module export declaration. pp.parseExport = function(node, exports) { this.next() // export * from '...' if (this.eat(tt.star)) { this.expectContextual("from") if (this.type !== tt.string) this.unexpected() node.source = this.parseExprAtom() this.semicolon() return this.finishNode(node, "ExportAllDeclaration") } if (this.eat(tt._default)) { // export default ... this.checkExport(exports, "default", this.lastTokStart) let isAsync if (this.type === tt._function || (isAsync = this.isAsyncFunction())) { let fNode = this.startNode() this.next() if (isAsync) this.next() node.declaration = this.parseFunction(fNode, "nullableID", false, isAsync) } else if (this.type === tt._class) { let cNode = this.startNode() node.declaration = this.parseClass(cNode, "nullableID") } else { node.declaration = this.parseMaybeAssign() this.semicolon() } return this.finishNode(node, "ExportDefaultDeclaration") } // export var|const|let|function|class ... if (this.shouldParseExportStatement()) { node.declaration = this.parseStatement(true) if (node.declaration.type === "VariableDeclaration") this.checkVariableExport(exports, node.declaration.declarations) else this.checkExport(exports, node.declaration.id.name, node.declaration.id.start) node.specifiers = [] node.source = null } else { // export { x, y as z } [from '...'] node.declaration = null node.specifiers = this.parseExportSpecifiers(exports) if (this.eatContextual("from")) { if (this.type !== tt.string) this.unexpected() node.source = this.parseExprAtom() } else { // check for keywords used as local names for (let spec of node.specifiers) { this.checkUnreserved(spec.local) } node.source = null } this.semicolon() } return this.finishNode(node, "ExportNamedDeclaration") } pp.checkExport = function(exports, name, pos) { if (!exports) return if (has(exports, name)) this.raiseRecoverable(pos, "Duplicate export '" + name + "'") exports[name] = true } pp.checkPatternExport = function(exports, pat) { let type = pat.type if (type == "Identifier") this.checkExport(exports, pat.name, pat.start) else if (type == "ObjectPattern") for (let prop of pat.properties) this.checkPatternExport(exports, prop) else if (type == "ArrayPattern") for (let elt of pat.elements) { if (elt) this.checkPatternExport(exports, elt) } else if (type == "Property") this.checkPatternExport(exports, pat.value) else if (type == "AssignmentPattern") this.checkPatternExport(exports, pat.left) else if (type == "RestElement") this.checkPatternExport(exports, pat.argument) else if (type == "ParenthesizedExpression") this.checkPatternExport(exports, pat.expression) } pp.checkVariableExport = function(exports, decls) { if (!exports) return for (let decl of decls) this.checkPatternExport(exports, decl.id) } pp.shouldParseExportStatement = function() { return this.type.keyword === "var" || this.type.keyword === "const" || this.type.keyword === "class" || this.type.keyword === "function" || this.isLet() || this.isAsyncFunction() } // Parses a comma-separated list of module exports. pp.parseExportSpecifiers = function(exports) { let nodes = [], first = true // 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 let node = this.startNode() node.local = this.parseIdent(true) node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local this.checkExport(exports, node.exported.name, node.exported.start) nodes.push(this.finishNode(node, "ExportSpecifier")) } return nodes } // Parses import declaration. pp.parseImport = function(node) { this.next() // import '...' if (this.type === tt.string) { node.specifiers = empty node.source = this.parseExprAtom() } else { node.specifiers = this.parseImportSpecifiers() this.expectContextual("from") node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected() } this.semicolon() return this.finishNode(node, "ImportDeclaration") } // Parses a comma-separated list of module imports. pp.parseImportSpecifiers = function() { let nodes = [], first = true if (this.type === tt.name) { // import defaultObj, { x, y as z } from '...' let node = this.startNode() node.local = this.parseIdent() this.checkLVal(node.local, "let") nodes.push(this.finishNode(node, "ImportDefaultSpecifier")) if (!this.eat(tt.comma)) return nodes } if (this.type === tt.star) { let node = this.startNode() this.next() this.expectContextual("as") node.local = this.parseIdent() this.checkLVal(node.local, "let") 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.afterTrailingComma(tt.braceR)) break } else first = false let node = this.startNode() node.imported = this.parseIdent(true) if (this.eatContextual("as")) { node.local = this.parseIdent() } else { this.checkUnreserved(node.imported) node.local = node.imported } this.checkLVal(node.local, "let") nodes.push(this.finishNode(node, "ImportSpecifier")) } return nodes } // Set `ExpressionStatement#directive` property for directive prologues. pp.adaptDirectivePrologue = function(statements) { for (let i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) { statements[i].directive = statements[i].expression.raw.slice(1, -1) } } pp.isDirectiveCandidate = function(statement) { return ( statement.type === "ExpressionStatement" && statement.expression.type === "Literal" && typeof statement.expression.value === "string" && // Reject parenthesized strings. (this.input[statement.start] === "\"" || this.input[statement.start] === "'") ) } acorn-5.5.3/src/tokencontext.js000066400000000000000000000107131325020065300164760ustar00rootroot00000000000000// The algorithm used to determine whether a regexp can appear at a // given point in the program is loosely based on sweet.js' approach. // See https://github.com/mozilla/sweet.js/wiki/design import {Parser} from "./state" import {types as tt} from "./tokentype" import {lineBreak} from "./whitespace" export class TokContext { constructor(token, isExpr, preserveSpace, override, generator) { this.token = token this.isExpr = !!isExpr this.preserveSpace = !!preserveSpace this.override = override this.generator = !!generator } } export const types = { b_stat: new TokContext("{", false), b_expr: new TokContext("{", true), b_tmpl: new TokContext("${", false), p_stat: new TokContext("(", false), p_expr: new TokContext("(", true), q_tmpl: new TokContext("`", true, true, p => p.tryReadTemplateToken()), f_stat: new TokContext("function", false), f_expr: new TokContext("function", true), f_expr_gen: new TokContext("function", true, false, null, true), f_gen: new TokContext("function", false, false, null, true) } const pp = Parser.prototype pp.initialContext = function() { return [types.b_stat] } pp.braceIsBlock = function(prevType) { let parent = this.curContext() if (parent === types.f_expr || parent === types.f_stat) return true if (prevType === tt.colon && (parent === types.b_stat || parent === types.b_expr)) return !parent.isExpr // The check for `tt.name && exprAllowed` detects whether we are // after a `yield` or `of` construct. See the `updateContext` for // `tt.name`. if (prevType === tt._return || prevType == tt.name && this.exprAllowed) return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof || prevType === tt.parenR || prevType == tt.arrow) return true if (prevType == tt.braceL) return parent === types.b_stat if (prevType == tt._var || prevType == tt.name) return false return !this.exprAllowed } pp.inGeneratorContext = function() { for (let i = this.context.length - 1; i >= 1; i--) { let context = this.context[i] if (context.token === "function") return context.generator } return false } pp.updateContext = function(prevType) { let update, type = this.type if (type.keyword && prevType == tt.dot) this.exprAllowed = false else if (update = type.updateContext) update.call(this, prevType) else this.exprAllowed = type.beforeExpr } // Token-specific context update code tt.parenR.updateContext = tt.braceR.updateContext = function() { if (this.context.length == 1) { this.exprAllowed = true return } let out = this.context.pop() if (out === types.b_stat && this.curContext().token === "function") { out = this.context.pop() } this.exprAllowed = !out.isExpr } tt.braceL.updateContext = function(prevType) { this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr) this.exprAllowed = true } tt.dollarBraceL.updateContext = function() { this.context.push(types.b_tmpl) this.exprAllowed = true } tt.parenL.updateContext = function(prevType) { let statementParens = prevType === tt._if || prevType === tt._for || prevType === tt._with || prevType === tt._while this.context.push(statementParens ? types.p_stat : types.p_expr) this.exprAllowed = true } tt.incDec.updateContext = function() { // tokExprAllowed stays unchanged } tt._function.updateContext = tt._class.updateContext = function(prevType) { if (prevType.beforeExpr && prevType !== tt.semi && prevType !== tt._else && !((prevType === tt.colon || prevType === tt.braceL) && this.curContext() === types.b_stat)) this.context.push(types.f_expr) else this.context.push(types.f_stat) this.exprAllowed = false } tt.backQuote.updateContext = function() { if (this.curContext() === types.q_tmpl) this.context.pop() else this.context.push(types.q_tmpl) this.exprAllowed = false } tt.star.updateContext = function(prevType) { if (prevType == tt._function) { let index = this.context.length - 1 if (this.context[index] === types.f_expr) this.context[index] = types.f_expr_gen else this.context[index] = types.f_gen } this.exprAllowed = true } tt.name.updateContext = function(prevType) { let allowed = false if (this.options.ecmaVersion >= 6) { if (this.value == "of" && !this.exprAllowed || this.value == "yield" && this.inGeneratorContext()) allowed = true } this.exprAllowed = allowed } acorn-5.5.3/src/tokenize.js000066400000000000000000000531451325020065300156070ustar00rootroot00000000000000import {isIdentifierStart, isIdentifierChar} from "./identifier" import {types as tt, keywords as keywordTypes} from "./tokentype" import {Parser} from "./state" import {SourceLocation} from "./locutil" import {RegExpValidationState} from "./regexp" import {lineBreak, lineBreakG, isNewLine, nonASCIIwhitespace} from "./whitespace" // Object type used to represent tokens. Note that normally, tokens // simply exist as properties on the parser object. This is only // used for the onToken callback and the external tokenizer. export class Token { constructor(p) { this.type = p.type this.value = p.value this.start = p.start this.end = p.end if (p.options.locations) this.loc = new SourceLocation(p, p.startLoc, p.endLoc) if (p.options.ranges) this.range = [p.start, p.end] } } // ## Tokenizer const pp = Parser.prototype // Move to the next token pp.next = function() { if (this.options.onToken) this.options.onToken(new Token(this)) this.lastTokEnd = this.end this.lastTokStart = this.start this.lastTokEndLoc = this.endLoc this.lastTokStartLoc = this.startLoc this.nextToken() } pp.getToken = function() { this.next() return new Token(this) } // If we're in an ES6 environment, make parsers iterable if (typeof Symbol !== "undefined") pp[Symbol.iterator] = function() { return { next: () => { let token = this.getToken() return { done: token.type === tt.eof, value: token } } } } // Toggle strict mode. Re-reads the next number or string to please // pedantic tests (`"use strict"; 010;` should fail). pp.curContext = function() { return this.context[this.context.length - 1] } // Read a single token, updating the parser object's token-related // properties. pp.nextToken = function() { let curContext = this.curContext() if (!curContext || !curContext.preserveSpace) this.skipSpace() this.start = this.pos if (this.options.locations) this.startLoc = this.curPosition() if (this.pos >= this.input.length) return this.finishToken(tt.eof) if (curContext.override) return curContext.override(this) else this.readToken(this.fullCharCodeAtPos()) } pp.readToken = function(code) { // Identifier or keyword. '\uXXXX' sequences are allowed in // identifiers, so '\' also dispatches to that. if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) return this.readWord() return this.getTokenFromCode(code) } pp.fullCharCodeAtPos = function() { let code = this.input.charCodeAt(this.pos) if (code <= 0xd7ff || code >= 0xe000) return code let next = this.input.charCodeAt(this.pos + 1) return (code << 10) + next - 0x35fdc00 } pp.skipBlockComment = function() { let startLoc = this.options.onComment && this.curPosition() let start = this.pos, end = this.input.indexOf("*/", this.pos += 2) if (end === -1) this.raise(this.pos - 2, "Unterminated comment") this.pos = end + 2 if (this.options.locations) { lineBreakG.lastIndex = start let match while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) { ++this.curLine this.lineStart = match.index + match[0].length } } if (this.options.onComment) this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, startLoc, this.curPosition()) } pp.skipLineComment = function(startSkip) { let start = this.pos let startLoc = this.options.onComment && this.curPosition() let ch = this.input.charCodeAt(this.pos += startSkip) while (this.pos < this.input.length && !isNewLine(ch)) { ch = this.input.charCodeAt(++this.pos) } if (this.options.onComment) this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, startLoc, this.curPosition()) } // Called at the start of the parse and after every token. Skips // whitespace and comments, and. pp.skipSpace = function() { loop: while (this.pos < this.input.length) { let ch = this.input.charCodeAt(this.pos) switch (ch) { case 32: case 160: // ' ' ++this.pos break case 13: if (this.input.charCodeAt(this.pos + 1) === 10) { ++this.pos } case 10: case 8232: case 8233: ++this.pos if (this.options.locations) { ++this.curLine this.lineStart = this.pos } break case 47: // '/' switch (this.input.charCodeAt(this.pos + 1)) { case 42: // '*' this.skipBlockComment() break case 47: this.skipLineComment(2) break default: break loop } break default: if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { ++this.pos } else { break loop } } } } // Called at the end of every token. Sets `end`, `val`, and // maintains `context` and `exprAllowed`, and skips the space after // the token, so that the next one's `start` will point at the // right position. pp.finishToken = function(type, val) { this.end = this.pos if (this.options.locations) this.endLoc = this.curPosition() let prevType = this.type this.type = type this.value = val this.updateContext(prevType) } // ### Token reading // This is the function that is called to fetch the next token. It // is somewhat obscure, because it works in character codes rather // than characters, and because operator parsing has been inlined // into it. // // All in the name of speed. // pp.readToken_dot = function() { let next = this.input.charCodeAt(this.pos + 1) if (next >= 48 && next <= 57) return this.readNumber(true) let next2 = this.input.charCodeAt(this.pos + 2) if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' this.pos += 3 return this.finishToken(tt.ellipsis) } else { ++this.pos return this.finishToken(tt.dot) } } pp.readToken_slash = function() { // '/' let next = this.input.charCodeAt(this.pos + 1) if (this.exprAllowed) { ++this.pos; return this.readRegexp() } if (next === 61) return this.finishOp(tt.assign, 2) return this.finishOp(tt.slash, 1) } pp.readToken_mult_modulo_exp = function(code) { // '%*' let next = this.input.charCodeAt(this.pos + 1) let size = 1 let tokentype = code === 42 ? tt.star : tt.modulo // exponentiation operator ** and **= if (this.options.ecmaVersion >= 7 && code == 42 && next === 42) { ++size tokentype = tt.starstar next = this.input.charCodeAt(this.pos + 2) } if (next === 61) return this.finishOp(tt.assign, size + 1) return this.finishOp(tokentype, size) } pp.readToken_pipe_amp = function(code) { // '|&' let next = this.input.charCodeAt(this.pos + 1) if (next === code) return this.finishOp(code === 124 ? tt.logicalOR : tt.logicalAND, 2) if (next === 61) return this.finishOp(tt.assign, 2) return this.finishOp(code === 124 ? tt.bitwiseOR : tt.bitwiseAND, 1) } pp.readToken_caret = function() { // '^' let next = this.input.charCodeAt(this.pos + 1) if (next === 61) return this.finishOp(tt.assign, 2) return this.finishOp(tt.bitwiseXOR, 1) } pp.readToken_plus_min = function(code) { // '+-' let next = this.input.charCodeAt(this.pos + 1) if (next === code) { if (next == 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 62 && (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { // A `-->` line comment this.skipLineComment(3) this.skipSpace() return this.nextToken() } return this.finishOp(tt.incDec, 2) } if (next === 61) return this.finishOp(tt.assign, 2) return this.finishOp(tt.plusMin, 1) } pp.readToken_lt_gt = function(code) { // '<>' let next = this.input.charCodeAt(this.pos + 1) let size = 1 if (next === code) { size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2 if (this.input.charCodeAt(this.pos + size) === 61) return this.finishOp(tt.assign, size + 1) return this.finishOp(tt.bitShift, size) } if (next == 33 && code == 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 45 && this.input.charCodeAt(this.pos + 3) == 45) { // `10;\n --> nothing", { type: "Program", body: [ { type: "ExpressionStatement", expression: { type: "AssignmentExpression", operator: "=", left: { type: "Identifier", name: "x" }, right: { type: "BinaryExpression", left: { type: "UpdateExpression", operator: "--", prefix: false, argument: { type: "Identifier", name: "y" } }, operator: ">", right: { type: "Literal", value: 10 } } } } ] }); test("'use strict';\nobject.static();", { type: "Program", body: [ { type: "ExpressionStatement", expression: { type: "Literal", value: "use strict", raw: "'use strict'" } }, { type: "ExpressionStatement", expression: { type: "CallExpression", callee: { type: "MemberExpression", object: { type: "Identifier", name: "object" }, property: { type: "Identifier", name: "static" }, computed: false }, arguments: [] } } ] }); // Failure tests testFail("{", "Unexpected token (1:1)"); testFail("}", "Unexpected token (1:0)"); testFail("3ea", "Invalid number (1:0)"); testFail("3in []", "Identifier directly after number (1:1)"); testFail("3e", "Invalid number (1:0)"); testFail("3e+", "Invalid number (1:0)"); testFail("3e-", "Invalid number (1:0)"); testFail("3x", "Identifier directly after number (1:1)"); testFail("3x0", "Identifier directly after number (1:1)"); testFail("0x", "Expected number in radix 16 (1:2)"); testFail("'use strict'; 09", "Invalid number (1:14)"); testFail("'use strict'; 018", "Invalid number (1:14)"); testFail("01a", "Identifier directly after number (1:2)"); testFail("3in[]", "Identifier directly after number (1:1)"); testFail("0x3in[]", "Identifier directly after number (1:3)"); testFail("\"Hello\nWorld\"", "Unterminated string constant (1:0)"); testFail("x\\", "Expecting Unicode escape sequence \\uXXXX (1:2)"); testFail("x\\u005c", "Invalid Unicode escape (1:1)"); testFail("x\\u002a", "Invalid Unicode escape (1:1)"); testFail("/", "Unterminated regular expression (1:1)"); testFail("/test", "Unterminated regular expression (1:1)"); testFail("var x = /[a-z]/\\ux", "Bad character escape sequence (1:17)"); testFail("3 = 4", "Assigning to rvalue (1:0)"); testFail("func() = 4", "Assigning to rvalue (1:0)"); testFail("(1 + 1) = 10", "Parenthesized pattern (1:0)"); testFail("1++", "Assigning to rvalue (1:0)"); testFail("1--", "Assigning to rvalue (1:0)"); testFail("++1", "Assigning to rvalue (1:2)"); testFail("--1", "Assigning to rvalue (1:2)"); testFail("for((1 + 1) in list) process(x);", "Parenthesized pattern (1:4)"); testFail("[", "Unexpected token (1:1)"); testFail("[,", "Unexpected token (1:2)"); testFail("1 + {", "Unexpected token (1:5)"); testFail("1 + { t:t ", "Unexpected token (1:10)"); testFail("1 + { t:t,", "Unexpected token (1:10)"); testFail("var x = /\n/", "Unterminated regular expression (1:9)"); testFail("var x = \"\n", "Unterminated string constant (1:8)"); testFail("var if = 42", "Unexpected keyword 'if' (1:4)"); testFail("i + 2 = 42", "Assigning to rvalue (1:0)"); testFail("+i = 42", "Assigning to rvalue (1:0)"); testFail("1 + (", "Unexpected token (1:5)"); testFail("\n\n\n{", "Unexpected token (4:1)"); testFail("\n/* Some multiline\ncomment */\n)", "Unexpected token (4:0)"); testFail("{ set 1 }", "Unexpected token (1:6)"); testFail("{ get 2 }", "Unexpected token (1:6)"); testFail("({ set: s(if) { } })", "Unexpected token (1:10)"); testFail("({ set s(.) { } })", "Unexpected token (1:9)"); testFail("({ set: s() { } })", "Unexpected token (1:12)"); testFail("({ set: s(a, b) { } })", "Unexpected token (1:16)"); testFail("({ get: g(d) { } })", "Unexpected token (1:13)"); testFail("({ get i() { }, i: 42 })", "Redefinition of property (1:16)"); testFail("({ i: 42, get i() { } })", "Redefinition of property (1:14)"); testFail("({ set i(x) { }, i: 42 })", "Redefinition of property (1:17)"); testFail("({ i: 42, set i(x) { } })", "Redefinition of property (1:14)"); testFail("({ get i() { }, get i() { } })", "Redefinition of property (1:20)"); testFail("({ set i(x) { }, set i(x) { } })", "Redefinition of property (1:21)"); testFail("'use strict'; ({ __proto__: 1, __proto__: 2 })", "Redefinition of property (1:31)"); testFail("function t(...) { }", "Unexpected token (1:11)"); testFail("function t(...) { }", "Unexpected token (1:14)", { ecmaVersion: 6 }); testFail("function t(...rest, b) { }", "Comma is not permitted after the rest element (1:18)", { ecmaVersion: 6 }); testFail("function t(if) { }", "Unexpected keyword 'if' (1:11)"); testFail("function t(true) { }", "Unexpected keyword 'true' (1:11)"); testFail("function t(false) { }", "Unexpected keyword 'false' (1:11)"); testFail("function t(null) { }", "Unexpected keyword 'null' (1:11)"); testFail("function null() { }", "Unexpected keyword 'null' (1:9)"); testFail("function true() { }", "Unexpected keyword 'true' (1:9)"); testFail("function false() { }", "Unexpected keyword 'false' (1:9)"); testFail("function if() { }", "Unexpected keyword 'if' (1:9)"); testFail("a b;", "Unexpected token (1:2)"); testFail("if.a;", "Unexpected token (1:2)"); testFail("a if;", "Unexpected token (1:2)"); testFail("a class;", "Unexpected token (1:2)"); testFail("break\n", "Unsyntactic break (1:0)"); testFail("break 1;", "Unexpected token (1:6)"); testFail("continue\n", "Unsyntactic continue (1:0)"); testFail("continue 2;", "Unexpected token (1:9)"); testFail("throw", "Unexpected token (1:5)"); testFail("throw;", "Unexpected token (1:5)"); testFail("for (var i, i2 in {});", "Unexpected token (1:15)"); testFail("for ((i in {}));", "Unexpected token (1:14)"); testFail("for (i + 1 in {});", "Assigning to rvalue (1:5)"); testFail("for (+i in {});", "Assigning to rvalue (1:5)"); testFail("if(false)", "Unexpected token (1:9)"); testFail("if(false) doThis(); else", "Unexpected token (1:24)"); testFail("do", "Unexpected token (1:2)"); testFail("while(false)", "Unexpected token (1:12)"); testFail("for(;;)", "Unexpected token (1:7)"); testFail("with(x)", "Unexpected token (1:7)"); testFail("try { }", "Missing catch or finally clause (1:0)"); testFail("‿ = 10", "Unexpected character '‿' (1:0)"); testFail("if(true) let a = 1;", "Unexpected token (1:13)"); testFail("switch (c) { default: default: }", "Multiple default clauses (1:22)"); testFail("new X().\"s\"", "Unexpected token (1:8)"); testFail("/*", "Unterminated comment (1:0)"); testFail("/*\n\n\n", "Unterminated comment (1:0)"); testFail("/**", "Unterminated comment (1:0)"); testFail("/*\n\n*", "Unterminated comment (1:0)"); testFail("/*hello", "Unterminated comment (1:0)"); testFail("/*hello *", "Unterminated comment (1:0)"); testFail("\n]", "Unexpected token (2:0)"); testFail("\r]", "Unexpected token (2:0)"); testFail("\r\n]", "Unexpected token (2:0)"); testFail("\n\r]", "Unexpected token (3:0)"); testFail("//\r\n]", "Unexpected token (2:0)"); testFail("//\n\r]", "Unexpected token (3:0)"); testFail("/a\\\n/", "Unterminated regular expression (1:1)"); testFail("//\r \n]", "Unexpected token (3:0)"); testFail("/*\r\n*/]", "Unexpected token (2:2)"); testFail("/*\n\r*/]", "Unexpected token (3:2)"); testFail("/*\r \n*/]", "Unexpected token (3:2)"); testFail("\\\\", "Expecting Unicode escape sequence \\uXXXX (1:1)"); testFail("\\u005c", "Invalid Unicode escape (1:0)"); testFail("\\x", "Expecting Unicode escape sequence \\uXXXX (1:1)"); testFail("\\u0000", "Invalid Unicode escape (1:0)"); testFail("‌ = []", "Unexpected character '‌' (1:0)"); testFail("‍ = []", "Unexpected character '‍' (1:0)"); testFail("\"\\", "Unterminated string constant (1:0)"); testFail("\"\\u", "Bad character escape sequence (1:3)"); testFail("return", "'return' outside of function (1:0)"); testFail("break", "Unsyntactic break (1:0)"); testFail("continue", "Unsyntactic continue (1:0)"); testFail("switch (x) { default: continue; }", "Unsyntactic continue (1:22)"); testFail("do { x } *", "Unexpected token (1:9)"); testFail("while (true) { break x; }", "Unsyntactic break (1:15)"); testFail("while (true) { continue x; }", "Unsyntactic continue (1:15)"); testFail("x: while (true) { (function () { break x; }); }", "Unsyntactic break (1:33)"); testFail("x: while (true) { (function () { continue x; }); }", "Unsyntactic continue (1:33)"); testFail("x: while (true) { (function () { break; }); }", "Unsyntactic break (1:33)"); testFail("x: while (true) { (function () { continue; }); }", "Unsyntactic continue (1:33)"); testFail("x: while (true) { x: while (true) { } }", "Label 'x' is already declared (1:18)"); testFail("(function () { 'use strict'; delete i; }())", "Deleting local variable in strict mode (1:29)"); testFail("function x() { '\\12'; 'use strict'; }", "Octal literal in strict mode (1:16)") testFail("(function () { 'use strict'; with (i); }())", "'with' in strict mode (1:29)"); testFail("function hello() {'use strict'; ({ i: 42, i: 42 }) }", "Redefinition of property (1:42)"); testFail("function hello() {'use strict'; ({ hasOwnProperty: 42, hasOwnProperty: 42 }) }", "Redefinition of property (1:55)"); testFail("function hello() {'use strict'; var eval = 10; }", "Binding eval in strict mode (1:36)"); testFail("function hello() {'use strict'; var arguments = 10; }", "Binding arguments in strict mode (1:36)"); testFail("function hello() {'use strict'; try { } catch (eval) { } }", "Binding eval in strict mode (1:47)"); testFail("function hello() {'use strict'; try { } catch (arguments) { } }", "Binding arguments in strict mode (1:47)"); testFail("function hello() {'use strict'; eval = 10; }", "Assigning to eval in strict mode (1:32)"); testFail("function hello() {'use strict'; arguments = 10; }", "Assigning to arguments in strict mode (1:32)"); testFail("function hello() {'use strict'; ++eval; }", "Assigning to eval in strict mode (1:34)"); testFail("function hello() {'use strict'; --eval; }", "Assigning to eval in strict mode (1:34)"); testFail("function hello() {'use strict'; ++arguments; }", "Assigning to arguments in strict mode (1:34)"); testFail("function hello() {'use strict'; --arguments; }", "Assigning to arguments in strict mode (1:34)"); testFail("function hello() {'use strict'; eval++; }", "Assigning to eval in strict mode (1:32)"); testFail("function hello() {'use strict'; eval--; }", "Assigning to eval in strict mode (1:32)"); testFail("function hello() {'use strict'; arguments++; }", "Assigning to arguments in strict mode (1:32)"); testFail("function hello() {'use strict'; arguments--; }", "Assigning to arguments in strict mode (1:32)"); testFail("function hello() {'use strict'; function eval() { } }", "Binding eval in strict mode (1:41)"); testFail("function hello() {'use strict'; function arguments() { } }", "Binding arguments in strict mode (1:41)"); testFail("function eval() {'use strict'; }", "Binding eval in strict mode (1:9)"); testFail("function arguments() {'use strict'; }", "Binding arguments in strict mode (1:9)"); testFail("function hello() {'use strict'; (function eval() { }()) }", "Binding eval in strict mode (1:42)"); testFail("function hello() {'use strict'; (function arguments() { }()) }", "Binding arguments in strict mode (1:42)"); testFail("(function eval() {'use strict'; })()", "Binding eval in strict mode (1:10)"); testFail("(function arguments() {'use strict'; })()", "Binding arguments in strict mode (1:10)"); testFail("function hello() {'use strict'; ({ s: function eval() { } }); }", "Binding eval in strict mode (1:47)"); testFail("(function package() {'use strict'; })()", "Binding package in strict mode (1:10)"); testFail("function hello() {'use strict'; ({ i: 10, set s(eval) { } }); }", "Binding eval in strict mode (1:48)"); testFail("function hello() {'use strict'; ({ set s(eval) { } }); }", "Binding eval in strict mode (1:41)"); testFail("function hello() {'use strict'; ({ s: function s(eval) { } }); }", "Binding eval in strict mode (1:49)"); testFail("function hello(eval) {'use strict';}", "Binding eval in strict mode (1:15)"); testFail("function hello(arguments) {'use strict';}", "Binding arguments in strict mode (1:15)"); testFail("function hello() { 'use strict'; function inner(eval) {} }", "Binding eval in strict mode (1:48)"); testFail("function hello() { 'use strict'; function inner(arguments) {} }", "Binding arguments in strict mode (1:48)"); testFail("function hello() { 'use strict'; \"\\1\"; }", "Octal literal in strict mode (1:34)"); testFail("function hello() { 'use strict'; \"\\00\"; }", "Octal literal in strict mode (1:34)"); testFail("function hello() { 'use strict'; \"\\000\"; }", "Octal literal in strict mode (1:34)"); testFail("function hello() { 'use strict'; 021; }", "Invalid number (1:33)"); testFail("function hello() { 'use strict'; ({ \"\\1\": 42 }); }", "Octal literal in strict mode (1:37)"); testFail("function hello() { 'use strict'; ({ 021: 42 }); }", "Invalid number (1:36)"); testFail("function hello() { \"use strict\"; function inner() { \"octal directive\\1\"; } }", "Octal literal in strict mode (1:68)"); testFail("function hello() { \"use strict\"; var implements; }", "The keyword 'implements' is reserved (1:37)"); testFail("function hello() { \"use strict\"; var interface; }", "The keyword 'interface' is reserved (1:37)"); testFail("function hello() { \"use strict\"; var package; }", "The keyword 'package' is reserved (1:37)"); testFail("function hello() { \"use strict\"; var private; }", "The keyword 'private' is reserved (1:37)"); testFail("function hello() { \"use strict\"; var protected; }", "The keyword 'protected' is reserved (1:37)"); testFail("function hello() { \"use strict\"; var public; }", "The keyword 'public' is reserved (1:37)"); testFail("function hello() { \"use strict\"; var static; }", "The keyword 'static' is reserved (1:37)"); testFail("function hello(static) { \"use strict\"; }", "Binding static in strict mode (1:15)"); testFail("function static() { \"use strict\"; }", "Binding static in strict mode (1:9)"); testFail("\"use strict\"; function static() { }", "The keyword 'static' is reserved (1:23)"); testFail("function a(t, t) { \"use strict\"; }", "Argument name clash (1:14)"); testFail("function a(eval) { \"use strict\"; }", "Binding eval in strict mode (1:11)"); testFail("function a(package) { \"use strict\"; }", "Binding package in strict mode (1:11)"); testFail("function a() { \"use strict\"; function b(t, t) { }; }", "Argument name clash (1:43)"); testFail("(function a(t, t) { \"use strict\"; })", "Argument name clash (1:15)"); testFail("function a() { \"use strict\"; (function b(t, t) { }); }", "Argument name clash (1:44)"); testFail("(function a(eval) { \"use strict\"; })", "Binding eval in strict mode (1:12)"); testFail("(function a(package) { \"use strict\"; })", "Binding package in strict mode (1:12)"); testFail("\"use strict\";function foo(){\"use strict\";}function bar(){var v = 015}", "Invalid number (1:65)"); testFail("var this = 10;", "Unexpected keyword 'this' (1:4)"); testFail("throw\n10;", "Illegal newline after throw (1:5)"); // ECMA < 6 mode should work as before testFail("const a;", "The keyword 'const' is reserved (1:0)"); testFail("let x;", "Unexpected token (1:4)"); testFail("const a = 1;", "The keyword 'const' is reserved (1:0)"); testFail("let a = 1;", "Unexpected token (1:4)"); testFail("for(const x = 0;;);", "The keyword 'const' is reserved (1:4)"); testFail("for(let x = 0;;);", "Unexpected token (1:8)"); testFail("function a(b = c) {}", "Unexpected token (1:13)"); testFail("switch (x) { something }", "Unexpected token (1:13)"); testFail("`abc`", "Unexpected character '`' (1:0)", {ecmaVersion: 5}); test("let++", { type: "Program", loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 5 } }, body: [ { type: "ExpressionStatement", loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 5 } }, expression: { type: "UpdateExpression", loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 5 } }, operator: "++", prefix: false, argument: { type: "Identifier", loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 3 } }, name: "let" } } } ] }); // ECMA 6 support test("let x", { type: "Program", body: [ { type: "VariableDeclaration", declarations: [ { type: "VariableDeclarator", id: { type: "Identifier", name: "x", loc: { start: { line: 1, column: 4 }, end: { line: 1, column: 5 } } }, init: null, loc: { start: { line: 1, column: 4 }, end: { line: 1, column: 5 } } } ], kind: "let", loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 5 } } } ], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 5 } } }, {ecmaVersion: 6, locations: true}); test("let x, y;", { type: "Program", body: [ { type: "VariableDeclaration", declarations: [ { type: "VariableDeclarator", id: { type: "Identifier", name: "x", loc: { start: { line: 1, column: 4 }, end: { line: 1, column: 5 } } }, init: null, loc: { start: { line: 1, column: 4 }, end: { line: 1, column: 5 } } }, { type: "VariableDeclarator", id: { type: "Identifier", name: "y", loc: { start: { line: 1, column: 7 }, end: { line: 1, column: 8 } } }, init: null, loc: { start: { line: 1, column: 7 }, end: { line: 1, column: 8 } } } ], kind: "let", loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 9 } } } ], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 9 } } }, {ecmaVersion: 6, locations: true}); test("let x = 42", { type: "Program", body: [ { type: "VariableDeclaration", declarations: [ { type: "VariableDeclarator", id: { type: "Identifier", name: "x", loc: { start: { line: 1, column: 4 }, end: { line: 1, column: 5 } } }, init: { type: "Literal", value: 42, loc: { start: { line: 1, column: 8 }, end: { line: 1, column: 10 } } }, loc: { start: { line: 1, column: 4 }, end: { line: 1, column: 10 } } } ], kind: "let", loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 10 } } } ], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 10 } } }, {ecmaVersion: 6, locations: true}); test("let eval = 42, arguments = 42", { type: "Program", body: [ { type: "VariableDeclaration", declarations: [ { type: "VariableDeclarator", id: { type: "Identifier", name: "eval", loc: { start: { line: 1, column: 4 }, end: { line: 1, column: 8 } } }, init: { type: "Literal", value: 42, loc: { start: { line: 1, column: 11 }, end: { line: 1, column: 13 } } }, loc: { start: { line: 1, column: 4 }, end: { line: 1, column: 13 } } }, { type: "VariableDeclarator", id: { type: "Identifier", name: "arguments", loc: { start: { line: 1, column: 15 }, end: { line: 1, column: 24 } } }, init: { type: "Literal", value: 42, loc: { start: { line: 1, column: 27 }, end: { line: 1, column: 29 } } }, loc: { start: { line: 1, column: 15 }, end: { line: 1, column: 29 } } } ], kind: "let", loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 29 } } } ], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 29 } } }, {ecmaVersion: 6, locations: true}); test("let x = 14, y = 3, z = 1977", { type: "Program", body: [ { type: "VariableDeclaration", declarations: [ { type: "VariableDeclarator", id: { type: "Identifier", name: "x", loc: { start: { line: 1, column: 4 }, end: { line: 1, column: 5 } } }, init: { type: "Literal", value: 14, loc: { start: { line: 1, column: 8 }, end: { line: 1, column: 10 } } }, loc: { start: { line: 1, column: 4 }, end: { line: 1, column: 10 } } }, { type: "VariableDeclarator", id: { type: "Identifier", name: "y", loc: { start: { line: 1, column: 12 }, end: { line: 1, column: 13 } } }, init: { type: "Literal", value: 3, loc: { start: { line: 1, column: 16 }, end: { line: 1, column: 17 } } }, loc: { start: { line: 1, column: 12 }, end: { line: 1, column: 17 } } }, { type: "VariableDeclarator", id: { type: "Identifier", name: "z", loc: { start: { line: 1, column: 19 }, end: { line: 1, column: 20 } } }, init: { type: "Literal", value: 1977, loc: { start: { line: 1, column: 23 }, end: { line: 1, column: 27 } } }, loc: { start: { line: 1, column: 19 }, end: { line: 1, column: 27 } } } ], kind: "let", loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 27 } } } ], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 27 } } }, {ecmaVersion: 6, locations: true}); test("for(let x = 0;;);", { type: "Program", body: [ { type: "ForStatement", init: { type: "VariableDeclaration", declarations: [ { type: "VariableDeclarator", id: { type: "Identifier", name: "x", loc: { start: { line: 1, column: 8 }, end: { line: 1, column: 9 } } }, init: { type: "Literal", value: 0, loc: { start: { line: 1, column: 12 }, end: { line: 1, column: 13 } } }, loc: { start: { line: 1, column: 8 }, end: { line: 1, column: 13 } } } ], kind: "let", loc: { start: { line: 1, column: 4 }, end: { line: 1, column: 13 } } }, test: null, update: null, body: { type: "EmptyStatement", loc: { start: { line: 1, column: 16 }, end: { line: 1, column: 17 } } }, loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 17 } } } ], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 17 } } }, {ecmaVersion: 6, locations: true}); test("for(let x = 0, y = 1;;);", { type: "Program", body: [ { type: "ForStatement", init: { type: "VariableDeclaration", declarations: [ { type: "VariableDeclarator", id: { type: "Identifier", name: "x", loc: { start: { line: 1, column: 8 }, end: { line: 1, column: 9 } } }, init: { type: "Literal", value: 0, loc: { start: { line: 1, column: 12 }, end: { line: 1, column: 13 } } }, loc: { start: { line: 1, column: 8 }, end: { line: 1, column: 13 } } }, { type: "VariableDeclarator", id: { type: "Identifier", name: "y", loc: { start: { line: 1, column: 15 }, end: { line: 1, column: 16 } } }, init: { type: "Literal", value: 1, loc: { start: { line: 1, column: 19 }, end: { line: 1, column: 20 } } }, loc: { start: { line: 1, column: 15 }, end: { line: 1, column: 20 } } } ], kind: "let", loc: { start: { line: 1, column: 4 }, end: { line: 1, column: 20 } } }, test: null, update: null, body: { type: "EmptyStatement", loc: { start: { line: 1, column: 23 }, end: { line: 1, column: 24 } } }, loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 24 } } } ], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 24 } } }, {ecmaVersion: 6, locations: true}); test("for (let x in list) process(x);", { type: "Program", body: [ { type: "ForInStatement", left: { type: "VariableDeclaration", declarations: [ { type: "VariableDeclarator", id: { type: "Identifier", name: "x", loc: { start: { line: 1, column: 9 }, end: { line: 1, column: 10 } } }, init: null, loc: { start: { line: 1, column: 9 }, end: { line: 1, column: 10 } } } ], kind: "let", loc: { start: { line: 1, column: 5 }, end: { line: 1, column: 10 } } }, right: { type: "Identifier", name: "list", loc: { start: { line: 1, column: 14 }, end: { line: 1, column: 18 } } }, body: { type: "ExpressionStatement", expression: { type: "CallExpression", callee: { type: "Identifier", name: "process", loc: { start: { line: 1, column: 20 }, end: { line: 1, column: 27 } } }, arguments: [ { type: "Identifier", name: "x", loc: { start: { line: 1, column: 28 }, end: { line: 1, column: 29 } } } ], loc: { start: { line: 1, column: 20 }, end: { line: 1, column: 30 } } }, loc: { start: { line: 1, column: 20 }, end: { line: 1, column: 31 } } }, loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 31 } } } ], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 31 } } }, {ecmaVersion: 6, locations: true}); test("const x = 42", { type: "Program", body: [ { type: "VariableDeclaration", declarations: [ { type: "VariableDeclarator", id: { type: "Identifier", name: "x", loc: { start: { line: 1, column: 6 }, end: { line: 1, column: 7 } } }, init: { type: "Literal", value: 42, loc: { start: { line: 1, column: 10 }, end: { line: 1, column: 12 } } }, loc: { start: { line: 1, column: 6 }, end: { line: 1, column: 12 } } } ], kind: "const", loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 12 } } } ], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 12 } } }, {ecmaVersion: 6, locations: true}); test("const eval = 42, arguments = 42", { type: "Program", body: [ { type: "VariableDeclaration", declarations: [ { type: "VariableDeclarator", id: { type: "Identifier", name: "eval", loc: { start: { line: 1, column: 6 }, end: { line: 1, column: 10 } } }, init: { type: "Literal", value: 42, loc: { start: { line: 1, column: 13 }, end: { line: 1, column: 15 } } }, loc: { start: { line: 1, column: 6 }, end: { line: 1, column: 15 } } }, { type: "VariableDeclarator", id: { type: "Identifier", name: "arguments", loc: { start: { line: 1, column: 17 }, end: { line: 1, column: 26 } } }, init: { type: "Literal", value: 42, loc: { start: { line: 1, column: 29 }, end: { line: 1, column: 31 } } }, loc: { start: { line: 1, column: 17 }, end: { line: 1, column: 31 } } } ], kind: "const", loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 31 } } } ], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 31 } } }, {ecmaVersion: 6, locations: true}); test("const x = 14, y = 3, z = 1977", { type: "Program", body: [ { type: "VariableDeclaration", declarations: [ { type: "VariableDeclarator", id: { type: "Identifier", name: "x", loc: { start: { line: 1, column: 6 }, end: { line: 1, column: 7 } } }, init: { type: "Literal", value: 14, loc: { start: { line: 1, column: 10 }, end: { line: 1, column: 12 } } }, loc: { start: { line: 1, column: 6 }, end: { line: 1, column: 12 } } }, { type: "VariableDeclarator", id: { type: "Identifier", name: "y", loc: { start: { line: 1, column: 14 }, end: { line: 1, column: 15 } } }, init: { type: "Literal", value: 3, loc: { start: { line: 1, column: 18 }, end: { line: 1, column: 19 } } }, loc: { start: { line: 1, column: 14 }, end: { line: 1, column: 19 } } }, { type: "VariableDeclarator", id: { type: "Identifier", name: "z", loc: { start: { line: 1, column: 21 }, end: { line: 1, column: 22 } } }, init: { type: "Literal", value: 1977, loc: { start: { line: 1, column: 25 }, end: { line: 1, column: 29 } } }, loc: { start: { line: 1, column: 21 }, end: { line: 1, column: 29 } } } ], kind: "const", loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 29 } } } ], loc: { start: { line: 1, column: 0 }, end: { line: 1, column: 29 } } }, {ecmaVersion: 6, locations: true}); testFail("const a;", "Unexpected token (1:7)", {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)"); testFail("for(var x of a);", "Unexpected token (1:10)"); // Assertion Tests test(function TestComments() { // Bear class function Bear(x,y,z) { this.position = [x||0,y||0,z||0] } Bear.prototype.roar = function(message) { return 'RAWWW: ' + message; // Whatever }; function Cat() { /* 1 2 3*/ } Cat.prototype.roar = function(message) { return 'MEOOWW: ' + /*stuff*/ message; }; }.toString().replace(/\r\n/g, '\n'), {}, { onComment: [ {type: "Line", value: " Bear class"}, {type: "Line", value: " Whatever"}, {type: "Block", value: [ " 1", " 2", " 3" ].join('\n')}, {type: "Block", value: "stuff"} ] }); test(" HTML comment", {}, { locations: true, onComment: [{ type: "Line", value: " HTML comment", loc: { start: { line: 2, column: 0 }, end: { line: 2, column: 16 } } }] }); var tokTypes = acorn.tokTypes; test('var x = (1 + 2)', {}, { locations: true, loose: false, onToken: [ { type: tokTypes._var, value: "var", loc: { start: {line: 1, column: 0}, end: {line: 1, column: 3} } }, { type: tokTypes.name, value: "x", loc: { start: {line: 1, column: 4}, end: {line: 1, column: 5} } }, { type: tokTypes.eq, value: "=", loc: { start: {line: 1, column: 6}, end: {line: 1, column: 7} } }, { type: tokTypes.parenL, value: undefined, loc: { start: {line: 1, column: 8}, end: {line: 1, column: 9} } }, { type: tokTypes.num, value: 1, loc: { start: {line: 1, column: 9}, end: {line: 1, column: 10} } }, { type: tokTypes.plusMin, value: "+", loc: { start: {line: 1, column: 11}, end: {line: 1, column: 12} } }, { type: tokTypes.num, value: 2, loc: { start: {line: 1, column: 13}, end: {line: 1, column: 14} } }, { type: tokTypes.parenR, value: undefined, loc: { start: {line: 1, column: 14}, end: {line: 1, column: 15} } }, { type: tokTypes.eof, value: undefined, loc: { start: {line: 1, column: 15}, end: {line: 1, column: 15} } } ] }); test("function f(f) { 'use strict'; }", {}); // https://github.com/acornjs/acorn/issues/180 test("#!/usr/bin/node\n;", {}, { allowHashBang: true, onComment: [{ type: "Line", value: "/usr/bin/node", start: 0, end: 15 }] }); // https://github.com/acornjs/acorn/issues/204 test("(function () {} / 1)", { type: "Program", body: [{ type: "ExpressionStatement", expression: { type: "BinaryExpression", left: { type: "FunctionExpression", id: null, params: [], body: { type: "BlockStatement", body: [] } }, operator: "/", right: {type: "Literal", value: 1} } }] }); test("function f() {} / 1 /", { type: "Program", body: [ { type: "FunctionDeclaration", id: {type: "Identifier", name: "f"}, params: [], body: { type: "BlockStatement", body: [] } }, { type: "ExpressionStatement", expression: { type: "Literal", regex: {pattern: " 1 ", flags: ""}, value: / 1 / } } ] }); // https://github.com/acornjs/acorn/issues/320 test("do /x/; while (false);", { type: "Program", body: [ { type: "DoWhileStatement", body: { type: "ExpressionStatement", expression: { type: "Literal", value: /x/, raw: "/x/", regex: { pattern: "x", flags: "" } } }, test: { type: "Literal", value: false, raw: "false" } } ] }); 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}) // https://github.com/acornjs/acorn/issues/275 testFail("({ get prop(x) {} })", "getter should have no params (1:11)"); testFail("({ set prop() {} })", "setter should have exactly one param (1:11)"); testFail("({ set prop(x, y) {} })", "setter should have exactly one param (1:11)"); // https://github.com/acornjs/acorn/issues/363 test("/[a-z]/gim", { type: "Program", body: [ { type: "ExpressionStatement", expression: { type: "Literal", value: /[a-z]/gim, regex: { pattern: "[a-z]", flags: "gim" } } } ] }); testFail("/[a-z]/u", "Invalid regular expression flag (1:1)"); testFail("/[a-z]/y", "Invalid regular expression flag (1:1)"); testFail("/[a-z]/s", "Invalid regular expression flag (1:1)"); testFail("/a/gg", "Duplicate regular expression flag (1:1)"); testFail("function(){}", "Unexpected token (1:8)"); test("0123. in/foo/i", { "type": "Program", "body": [ { "type": "ExpressionStatement", "expression": { "type": "BinaryExpression", "left": { "type": "BinaryExpression", "left": { "type": "MemberExpression", "object": { "type": "Literal", "value": 83, "raw": "0123" }, "property": { "type": "Identifier", "name": "in" }, "computed": false }, "operator": "/", "right": { "type": "Identifier", "name": "foo" } }, "operator": "/", "right": { "type": "Identifier", "name": "i" } } } ] }) test("0128", { "type": "Program", "body": [ { "type": "ExpressionStatement", "expression": { "type": "Literal", "value": 128, "raw": "0128" } } ] }) testFail("07.5", "Unexpected token (1:2)") test("08.5", { "type": "Program", "body": [ { "type": "ExpressionStatement", "expression": { "type": "Literal", "value": 8.5, "raw": "08.5" } } ] }) test("undefined", {}, { ecmaVersion: 8 }) testFail("\\u{74}rue", "Escape sequence in keyword true (1:0)", {ecmaVersion: 6}) testFail("export { X \\u0061s Y }", "Unexpected token (1:11)", {ecmaVersion: 7, sourceType: "module"}) testFail("import X fro\\u006d 'x'", "Unexpected token (1:9)", {ecmaVersion: 7, sourceType: "module"}) testFail("le\\u0074 x = 5", "Unexpected token (1:9)", {ecmaVersion: 6}) testFail("(function* () { y\\u0069eld 10 })", "Can not use 'yield' as identifier inside a generator (1:16)", {ecmaVersion: 6}) testFail("(async function() { aw\\u0061it x })", "Can not use 'await' as identifier inside an async function (1:20)", {ecmaVersion: 8}) testFail("(\\u0061sync function() { await x })", "Unexpected token (1:12)", {ecmaVersion: 8}) testFail("(\\u0061sync () => { await x })", "Unexpected token (1:15)", {ecmaVersion: 8}) testFail("\\u0061sync x => { await x }", "Unexpected token (1:11)", {ecmaVersion: 8}) testFail("class X { \\u0061sync x() { await x } }", "Unexpected token (1:21)", {ecmaVersion: 8}) testFail("class X { static \\u0061sync x() { await x } }", "Unexpected token (1:28)", {ecmaVersion: 8}) testFail("({ ge\\u0074 x() {} })", "Unexpected token (1:12)") testFail("export \\u0061sync function y() { await x }", "Unexpected token (1:7)", {ecmaVersion: 8, sourceType: "module"}) testFail("export default \\u0061sync function () { await x }", "Unexpected token (1:26)", {ecmaVersion: 8, sourceType: "module"}) test("(\\u0061sync ())", { "type": "Program", "start": 0, "end": 15, "body": [ { "type": "ExpressionStatement", "start": 0, "end": 15, "expression": { "type": "CallExpression", "start": 1, "end": 14, "callee": { "type": "Identifier", "start": 1, "end": 11, "name": "async" }, "arguments": [] } } ], "sourceType": "script" }, {ecmaVersion: 8}) testFail("({ \\u0061sync x() { await x } })", "Unexpected token (1:14)", {ecmaVersion: 8}) testFail("for (x \\u006ff y) {}", "Unexpected token (1:7)", {ecmaVersion: 6}) testFail("function x () { new.ta\\u0072get }", "The only valid meta property for new is new.target (1:20)", {ecmaVersion: 6}) testFail("class X { st\\u0061tic y() {} }", "Unexpected token (1:22)", {ecmaVersion: 6}) testFail("(x=1)=2", "Parenthesized pattern (1:0)") test("(foo = [])[0] = 4;", {}) test("for ((foo = []).bar in {}) {}", {}) test("((b), a=1)", {}) test("(x) = 1", {}) testFail("try {} catch (foo) { var foo; }", "Identifier 'foo' has already been declared (1:25)") testFail("try {} catch (foo) { let foo; }", "Identifier 'foo' has already been declared (1:25)", {ecmaVersion: 6}) testFail("try {} catch (foo) { try {} catch (_) { var foo; } }", "Identifier 'foo' has already been declared (1:44)") testFail("try {} catch ([foo]) { var foo; }", "Identifier 'foo' has already been declared (1:27)", {ecmaVersion: 6}) testFail("try {} catch ({ foo }) { var foo; }", "Identifier 'foo' has already been declared (1:29)", {ecmaVersion: 6}) testFail("try {} catch ([foo, foo]) {}", "Identifier 'foo' has already been declared (1:20)", {ecmaVersion: 6}) testFail("try {} catch ({ a: foo, b: { c: [foo] } }) {}", "Identifier 'foo' has already been declared (1:33)", {ecmaVersion: 6}) testFail("let foo; try {} catch (foo) {} let foo;", "Identifier 'foo' has already been declared (1:35)", {ecmaVersion: 6}) testFail("try {} catch (foo) { function foo() {} }", "Identifier 'foo' has already been declared (1:30)") test("try {} catch (foo) {} var foo;", {}) test("try {} catch (foo) {} let foo;", {}, {ecmaVersion: 6}) test("try {} catch (foo) { { let foo; } }", {}, {ecmaVersion: 6}) test("try {} catch (foo) { function x() { var foo; } }", {}, {ecmaVersion: 6}) test("try {} catch (foo) { function x(foo) {} }", {}, {ecmaVersion: 6}) test("'use strict'; let foo = function foo() {}", {}, {ecmaVersion: 6}) test("/**/ --> comment\n", {}) test("x.class++", {})