push all website files

This commit is contained in:
Jacob Levine
2019-01-06 13:14:45 -06:00
parent d7301e26c3
commit d2d5d4c04e
15662 changed files with 2166516 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
/.project
node_modules

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015,2016 Matt Woolf (MatAtBread, MatAtWork)
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.

View File

@@ -0,0 +1,164 @@
[![NPM](https://nodei.co/npm/acorn-es7-plugin.png?downloads=true&downloadRank=true)](https://nodei.co/npm/acorn-es7-plugin/)
acorn-es7-plugin
======
acorn-es7-plugin is a plugin for the [Acorn](https://github.com/marijnh/acorn) parser that generates ESTrees following the ['experimental' specification](https://github.com/estree/estree/blob/master/experimental/async-functions.md) for asynchronous functions.
npm install --save acorn-es7-plugin
Usage
=====
Adding the plugin
// Require acorn as usual
var acorn = require("acorn");
// Add the es7-plugin
require('./acorn-es7-plugin')(acorn) ;
Using the plugin
var code = "async function x(){ if (x) return await(x-1) ; return 0 ; }\n";
var ast = acorn.parse(code,{
// Specify use of the plugin
plugins:{asyncawait:true},
// Specify the ecmaVersion
ecmaVersion:7
}) ;
// Show the AST
console.log(JSON.stringify(ast,null,2)) ;
Output:
{
"type": "Program",
"body": [
{
"type": "FunctionDeclaration",
"id": {
"type": "Identifier",
"name": "x"
},
"generator": false,
"expression": false,
"params": [],
"body": {
"type": "BlockStatement",
"body": [
{
"type": "IfStatement",
"test": {
"type": "Identifier",
"name": "x"
},
"consequent": {
"type": "ReturnStatement",
"argument": {
"type": "AwaitExpression",
"operator": "await",
"argument": {
"type": "BinaryExpression",
"left": {
"type": "Identifier",
"name": "x"
},
"operator": "-",
"right": {
"type": "Literal",
"value": 1,
"raw": "1"
}
}
}
},
"alternate": null
},
{
"type": "ReturnStatement",
"argument": {
"type": "Literal",
"value": 0,
"raw": "0"
}
}
]
},
"async": true
}
],
"sourceType": "script"
}
Options & Compliance
====================
The parser attempts to enforce strict contextualisation of `async` and `await`. Specifically, `async` is only a keyword if it precedes a function declaration, function expression or arrow function. `await` is only a keyword inside an `async` function. Outside of these contexts, both tokens are treated as identifiers (as they were in ES6 and earlier).
When using the plugin, you can supply an object in place of the 'true' flag with the following options.
| flag | meaning |
|------|---------|
| awaitAnywhere | If `await` is used outside of an async function and could not be an identifier, generate an AwaitExpression node. This typically means you can use `await` anywhere _except_ when its argument would require parentheses, as this parses to a call to 'await(....)'. Should not be used with inAsyncFunction option |
| inAsyncFunction | Parse the code as if it is the body of an `async function`. This means `await` cannot be an identifier and is always an AwaitExpression, even if the argument is parenthesized. Should not be used with the awaitAnywhere option |
| asyncExits | Allow the additional sequences `async return <optional-expression>` and `async throw <expression>`. These sequences are used with [nodent](https://github.com/MatAtBread/nodent). In each case, as with async functions, a standard ReturnStatement (or ThrowStatement) node is generated, with an additional member 'async' set to true.
The parser also accepts async getters in object literals and classes, which is currently disallowed by the ES7 specification.
Changelog
=========
30-Mar-17: v1.1.7
- Fix parsing of IIAFE `(async function (){ }())` with acorn v3.
07-Oct-16: v1.1.1
- Fix disambiguation of async, get and set tokens (and add tests) when defining object properties:
| Code | Interpretation
|-----------------------|-------------------------|
| `get async(){}` | Is a standard ES6 getter called 'async'
| `set async(v){}` | Is a standard ES6 setter called 'async'
| `async get(...){}` | Is a standard ES7 async method called 'get'
| `async set(...){}` | Is a standard ES7 async method called 'set'
| `async get x(){}` | Is an extension that defines an async getter called 'x'
| `get async x(){}` | Is an extension that defines an async getter called 'x', but is deprecated (`async` should proceed `get`)
In previous version of the plugin, the standard ES7 constructs were hidden by the plugin extensions and a SyntaxError was incorrectly thrown
25-Sep-16: v1.1.0
- Update to work with acorn v4 if present. Note that `async` and `await` are fully parsed by acorn v4. The only use case for the plugin with acorn v4 is with the flags above which are enable specific parsing modes.
24-Sep-16: v1.0.18
- Correctly parse `async(()=>0)` as a call to the Identifer 'async', not a failed attempt to define an async arrow.
20-Jul-16: v1.0.17
- Correctly set non-standard "range" property on async nodes, as used by Webpack
27-Jun-16: v1.0.15
- Fix issue parsing async methods in classes and object literals which (incorrectly) required the `awaitAnywhere` option ([see https://github.com/MatAtBread/acorn-es7-plugin/issues/12](https://github.com/MatAtBread/acorn-es7-plugin/issues/12))
03-May-16: v1.0.14
- Correctly parse async statements containing comments.
- Implement the option inAsyncFunction
03-May-16: v1.0.13
- Correctly parse the statement `export async function name(){...}` as _async function name(){...}_ is a valid named declaration.
26-Feb-16: v1.0.12
- Updated to return the original acorn object on installation. See https://github.com/MatAtBread/acorn-es7-plugin/pull/4
19-Dec-15: v1.0.11
- Generate error if 'await' is used as an identifier within an async function.
10-Dec-15: v1.0.10
- Update the plugin code to remove 'async' and 'await' from the super-strict keyword tests introduced in acorn v2.6.x that generate parse errors before the plugin gets a chance to manage them.

View File

@@ -0,0 +1,17 @@
module.exports = function(acorn) {
switch (parseInt(acorn.version)) {
case 2:
case 3:
acorn.plugins.asyncawait = require('./acorn-v3') ;
break ;
case 4:
acorn.plugins.asyncawait = require('./acorn-v4') ;
break ;
case 5:
acorn.plugins.asyncawait = require('./acorn-v4') ;
break ;
default:
throw new Error("acorn-es7-plugin requires Acorn v2, 3, 4 or 5") ;
}
return acorn
}

View File

@@ -0,0 +1,333 @@
var NotAsync = {} ;
var asyncExit = /^async[\t ]+(return|throw)/ ;
var asyncFunction = /^async[\t ]+function/ ;
var atomOrPropertyOrLabel = /^\s*[():;]/ ;
var removeComments = /([^\n])\/\*(\*(?!\/)|[^\n*])*\*\/([^\n])/g ;
var matchAsyncGet = /\s*(get|set)\s*\(/ ;
function hasLineTerminatorBeforeNext(st, since) {
return st.lineStart >= since;
}
function test(regex,st,noComment) {
var src = st.input.slice(st.start) ;
if (noComment) {
src = src.replace(removeComments,"$1 $3") ;
}
return regex.test(src);
}
/* Create a new parser derived from the specified parser, so that in the
* event of an error we can back out and try again */
function subParse(parser, pos, extensions,parens) {
var p = new parser.constructor(parser.options, parser.input, pos);
if (extensions)
for (var k in extensions)
p[k] = extensions[k] ;
var src = parser ;
var dest = p ;
['inFunction','inAsyncFunction','inAsync','inGenerator','inModule'].forEach(function(k){
if (k in src)
dest[k] = src[k] ;
}) ;
if (parens)
p.options.preserveParens = true ;
p.nextToken();
return p;
}
//TODO: Implement option noAsyncGetters
function asyncAwaitPlugin (parser,options){
var es7check = function(){} ;
parser.extend("initialContext",function(base){
return function(){
if (this.options.ecmaVersion < 7) {
es7check = function(node) {
parser.raise(node.start,"async/await keywords only available when ecmaVersion>=7") ;
} ;
}
this.reservedWords = new RegExp(this.reservedWords.toString().replace(/await|async/g,"").replace("|/","/").replace("/|","/").replace("||","|")) ;
this.reservedWordsStrict = new RegExp(this.reservedWordsStrict.toString().replace(/await|async/g,"").replace("|/","/").replace("/|","/").replace("||","|")) ;
this.reservedWordsStrictBind = new RegExp(this.reservedWordsStrictBind.toString().replace(/await|async/g,"").replace("|/","/").replace("/|","/").replace("||","|")) ;
this.inAsyncFunction = options.inAsyncFunction ;
if (options.awaitAnywhere && options.inAsyncFunction)
parser.raise(node.start,"The options awaitAnywhere and inAsyncFunction are mutually exclusive") ;
return base.apply(this,arguments);
}
}) ;
parser.extend("shouldParseExportStatement",function(base){
return function(){
if (this.type.label==='name' && this.value==='async' && test(asyncFunction,this)) {
return true ;
}
return base.apply(this,arguments) ;
}
}) ;
parser.extend("parseStatement",function(base){
return function (declaration, topLevel) {
var start = this.start;
var startLoc = this.startLoc;
if (this.type.label==='name') {
if (test(asyncFunction,this,true)) {
var wasAsync = this.inAsyncFunction ;
try {
this.inAsyncFunction = true ;
this.next() ;
var r = this.parseStatement(declaration, topLevel) ;
r.async = true ;
r.start = start;
r.loc && (r.loc.start = startLoc);
r.range && (r.range[0] = start);
return r ;
} finally {
this.inAsyncFunction = wasAsync ;
}
} else if ((typeof options==="object" && options.asyncExits) && test(asyncExit,this)) {
// NON-STANDARD EXTENSION iff. options.asyncExits is set, the
// extensions 'async return <expr>?' and 'async throw <expr>?'
// are enabled. In each case they are the standard ESTree nodes
// with the flag 'async:true'
this.next() ;
var r = this.parseStatement(declaration, topLevel) ;
r.async = true ;
r.start = start;
r.loc && (r.loc.start = startLoc);
r.range && (r.range[0] = start);
return r ;
}
}
return base.apply(this,arguments);
}
}) ;
parser.extend("parseIdent",function(base){
return function(liberal){
var id = base.apply(this,arguments);
if (this.inAsyncFunction && id.name==='await') {
if (arguments.length===0) {
this.raise(id.start,"'await' is reserved within async functions") ;
}
}
return id ;
}
}) ;
parser.extend("parseExprAtom",function(base){
return function(refShorthandDefaultPos){
var start = this.start ;
var startLoc = this.startLoc;
var rhs,r = base.apply(this,arguments);
if (r.type==='Identifier') {
if (r.name==='async' && !hasLineTerminatorBeforeNext(this, r.end)) {
// Is this really an async function?
var isAsync = this.inAsyncFunction ;
try {
this.inAsyncFunction = true ;
var pp = this ;
var inBody = false ;
var parseHooks = {
parseFunctionBody:function(node,isArrowFunction){
try {
var wasInBody = inBody ;
inBody = true ;
return pp.parseFunctionBody.apply(this,arguments) ;
} finally {
inBody = wasInBody ;
}
},
raise:function(){
try {
return pp.raise.apply(this,arguments) ;
} catch(ex) {
throw inBody?ex:NotAsync ;
}
}
} ;
rhs = subParse(this,this.start,parseHooks,true).parseExpression() ;
if (rhs.type==='SequenceExpression')
rhs = rhs.expressions[0] ;
if (rhs.type === 'CallExpression')
rhs = rhs.callee ;
if (rhs.type==='FunctionExpression' || rhs.type==='FunctionDeclaration' || rhs.type==='ArrowFunctionExpression') {
// Because we don't know if the top level parser supprts preserveParens, we have to re-parse
// without it set
rhs = subParse(this,this.start,parseHooks).parseExpression() ;
if (rhs.type==='SequenceExpression')
rhs = rhs.expressions[0] ;
if (rhs.type === 'CallExpression')
rhs = rhs.callee ;
rhs.async = true ;
rhs.start = start;
rhs.loc && (rhs.loc.start = startLoc);
rhs.range && (rhs.range[0] = start);
this.pos = rhs.end;
this.end = rhs.end ;
this.endLoc = rhs.endLoc ;
this.next();
es7check(rhs) ;
return rhs ;
}
} catch (ex) {
if (ex!==NotAsync)
throw ex ;
}
finally {
this.inAsyncFunction = isAsync ;
}
}
else if (r.name==='await') {
var n = this.startNodeAt(r.start, r.loc && r.loc.start);
if (this.inAsyncFunction) {
rhs = this.parseExprSubscripts() ;
n.operator = 'await' ;
n.argument = rhs ;
n = this.finishNodeAt(n,'AwaitExpression', rhs.end, rhs.loc && rhs.loc.end) ;
es7check(n) ;
return n ;
}
// NON-STANDARD EXTENSION iff. options.awaitAnywhere is true,
// an 'AwaitExpression' is allowed anywhere the token 'await'
// could not be an identifier with the name 'await'.
// Look-ahead to see if this is really a property or label called async or await
if (this.input.slice(r.end).match(atomOrPropertyOrLabel)) {
if (!options.awaitAnywhere && this.options.sourceType === 'module')
return this.raise(r.start,"'await' is reserved within modules") ;
return r ; // This is a valid property name or label
}
if (typeof options==="object" && options.awaitAnywhere) {
start = this.start ;
rhs = subParse(this,start-4).parseExprSubscripts() ;
if (rhs.end<=start) {
rhs = subParse(this,start).parseExprSubscripts() ;
n.operator = 'await' ;
n.argument = rhs ;
n = this.finishNodeAt(n,'AwaitExpression', rhs.end, rhs.loc && rhs.loc.end) ;
this.pos = rhs.end;
this.end = rhs.end ;
this.endLoc = rhs.endLoc ;
this.next();
es7check(n) ;
return n ;
}
}
if (!options.awaitAnywhere && this.options.sourceType === 'module')
return this.raise(r.start,"'await' is reserved within modules") ;
}
}
return r ;
}
}) ;
parser.extend('finishNodeAt',function(base){
return function(node,type,pos,loc) {
if (node.__asyncValue) {
delete node.__asyncValue ;
node.value.async = true ;
}
return base.apply(this,arguments) ;
}
}) ;
parser.extend('finishNode',function(base){
return function(node,type) {
if (node.__asyncValue) {
delete node.__asyncValue ;
node.value.async = true ;
}
return base.apply(this,arguments) ;
}
}) ;
var allowedPropSpecifiers = {
get:true,
set:true,
async:true
};
parser.extend("parsePropertyName",function(base){
return function (prop) {
var prevName = prop.key && prop.key.name ;
var key = base.apply(this,arguments) ;
if (key.type === "Identifier" && (key.name === "async") && !hasLineTerminatorBeforeNext(this, key.end)) {
// Look-ahead to see if this is really a property or label called async or await
if (!this.input.slice(key.end).match(atomOrPropertyOrLabel)){
// Cheese - eliminate the cases 'async get(){}' and async set(){}'
if (matchAsyncGet.test(this.input.slice(key.end))) {
key = base.apply(this,arguments) ;
prop.__asyncValue = true ;
} else {
es7check(prop) ;
if (prop.kind === 'set')
this.raise(key.start,"'set <member>(value)' cannot be be async") ;
key = base.apply(this,arguments) ;
if (key.type==='Identifier') {
if (key.name==='set')
this.raise(key.start,"'set <member>(value)' cannot be be async") ;
}
prop.__asyncValue = true ;
}
}
}
return key;
};
}) ;
parser.extend("parseClassMethod",function(base){
return function (classBody, method, isGenerator) {
var wasAsync ;
if (method.__asyncValue) {
if (method.kind==='constructor')
this.raise(method.start,"class constructor() cannot be be async") ;
wasAsync = this.inAsyncFunction ;
this.inAsyncFunction = true ;
}
var r = base.apply(this,arguments) ;
this.inAsyncFunction = wasAsync ;
return r ;
}
}) ;
parser.extend("parseMethod",function(base){
return function (isGenerator) {
var wasAsync ;
if (this.__currentProperty && this.__currentProperty.__asyncValue) {
wasAsync = this.inAsyncFunction ;
this.inAsyncFunction = true ;
}
var r = base.apply(this,arguments) ;
this.inAsyncFunction = wasAsync ;
return r ;
}
}) ;
parser.extend("parsePropertyValue",function(base){
return function (prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors) {
var prevProp = this.__currentProperty ;
this.__currentProperty = prop ;
var wasAsync ;
if (prop.__asyncValue) {
wasAsync = this.inAsyncFunction ;
this.inAsyncFunction = true ;
}
var r = base.apply(this,arguments) ;
this.inAsyncFunction = wasAsync ;
this.__currentProperty = prevProp ;
return r ;
}
}) ;
}
module.exports = asyncAwaitPlugin ;

View File

@@ -0,0 +1,194 @@
var asyncExit = /^async[\t ]+(return|throw)/ ;
var atomOrPropertyOrLabel = /^\s*[):;]/ ;
var removeComments = /([^\n])\/\*(\*(?!\/)|[^\n*])*\*\/([^\n])/g ;
function hasLineTerminatorBeforeNext(st, since) {
return st.lineStart >= since;
}
function test(regex,st,noComment) {
var src = st.input.slice(st.start) ;
if (noComment) {
src = src.replace(removeComments,"$1 $3") ;
}
return regex.test(src);
}
/* Create a new parser derived from the specified parser, so that in the
* event of an error we can back out and try again */
function subParse(parser, pos, extensions) {
var p = new parser.constructor(parser.options, parser.input, pos);
if (extensions)
for (var k in extensions)
p[k] = extensions[k] ;
var src = parser ;
var dest = p ;
['inFunction','inAsync','inGenerator','inModule'].forEach(function(k){
if (k in src)
dest[k] = src[k] ;
}) ;
p.nextToken();
return p;
}
function asyncAwaitPlugin (parser,options){
if (!options || typeof options !== "object")
options = {} ;
parser.extend("parse",function(base){
return function(){
this.inAsync = options.inAsyncFunction ;
if (options.awaitAnywhere && options.inAsyncFunction)
parser.raise(node.start,"The options awaitAnywhere and inAsyncFunction are mutually exclusive") ;
return base.apply(this,arguments);
}
}) ;
parser.extend("parseStatement",function(base){
return function (declaration, topLevel) {
var start = this.start;
var startLoc = this.startLoc;
if (this.type.label==='name') {
if ((options.asyncExits) && test(asyncExit,this)) {
// TODO: Ensure this function is itself nested in an async function or Method
this.next() ;
var r = this.parseStatement(declaration, topLevel) ;
r.async = true ;
r.start = start;
r.loc && (r.loc.start = startLoc);
r.range && (r.range[0] = start);
return r ;
}
}
return base.apply(this,arguments);
}
}) ;
parser.extend("parseIdent",function(base){
return function(liberal) {
if (this.options.sourceType==='module' && this.options.ecmaVersion >= 8 && options.awaitAnywhere)
return base.call(this,true) ; // Force liberal mode if awaitAnywhere is set
return base.apply(this,arguments) ;
}
}) ;
parser.extend("parseExprAtom",function(base){
var NotAsync = {};
return function(refShorthandDefaultPos){
var start = this.start ;
var startLoc = this.startLoc;
var rhs,r = base.apply(this,arguments);
if (r.type==='Identifier') {
if (r.name==='await' && !this.inAsync) {
if (options.awaitAnywhere) {
var n = this.startNodeAt(r.start, r.loc && r.loc.start);
start = this.start ;
var parseHooks = {
raise:function(){
try {
return pp.raise.apply(this,arguments) ;
} catch(ex) {
throw /*inBody?ex:*/NotAsync ;
}
}
} ;
try {
rhs = subParse(this,start-4,parseHooks).parseExprSubscripts() ;
if (rhs.end<=start) {
rhs = subParse(this,start,parseHooks).parseExprSubscripts() ;
n.argument = rhs ;
n = this.finishNodeAt(n,'AwaitExpression', rhs.end, rhs.loc && rhs.loc.end) ;
this.pos = rhs.end;
this.end = rhs.end ;
this.endLoc = rhs.endLoc ;
this.next();
return n ;
}
} catch (ex) {
if (ex===NotAsync)
return r ;
throw ex ;
}
}
}
}
return r ;
}
}) ;
var allowedPropValues = {
undefined:true,
get:true,
set:true,
static:true,
async:true,
constructor:true
};
parser.extend("parsePropertyName",function(base){
return function (prop) {
var prevName = prop.key && prop.key.name ;
var key = base.apply(this,arguments) ;
if (this.value==='get') {
prop.__maybeStaticAsyncGetter = true ;
}
var next ;
if (allowedPropValues[this.value])
return key ;
if (key.type === "Identifier" && (key.name === "async" || prevName === "async") && !hasLineTerminatorBeforeNext(this, key.end)
// Look-ahead to see if this is really a property or label called async or await
&& !this.input.slice(key.end).match(atomOrPropertyOrLabel)) {
if (prop.kind === 'set' || key.name === 'set')
this.raise(key.start,"'set <member>(value)' cannot be be async") ;
else {
this.__isAsyncProp = true ;
key = base.apply(this,arguments) ;
if (key.type==='Identifier') {
if (key.name==='set')
this.raise(key.start,"'set <member>(value)' cannot be be async") ;
}
}
} else {
delete prop.__maybeStaticAsyncGetter ;
}
return key;
};
}) ;
parser.extend("parseClassMethod",function(base){
return function (classBody, method, isGenerator) {
var r = base.apply(this,arguments) ;
if (method.__maybeStaticAsyncGetter) {
delete method.__maybeStaticAsyncGetter ;
if (method.key.name!=='get')
method.kind = "get" ;
}
return r ;
}
}) ;
parser.extend("parseFunctionBody",function(base){
return function (node, isArrowFunction) {
var wasAsync = this.inAsync ;
if (this.__isAsyncProp) {
node.async = true ;
this.inAsync = true ;
delete this.__isAsyncProp ;
}
var r = base.apply(this,arguments) ;
this.inAsync = wasAsync ;
return r ;
}
}) ;
}
module.exports = asyncAwaitPlugin ;

View File

@@ -0,0 +1,53 @@
{
"_from": "acorn-es7-plugin@^1.0.12",
"_id": "acorn-es7-plugin@1.1.7",
"_inBundle": false,
"_integrity": "sha1-8u4fMiipDurRJF+asZIusucdM2s=",
"_location": "/acorn-es7-plugin",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "acorn-es7-plugin@^1.0.12",
"name": "acorn-es7-plugin",
"escapedName": "acorn-es7-plugin",
"rawSpec": "^1.0.12",
"saveSpec": null,
"fetchSpec": "^1.0.12"
},
"_requiredBy": [
"/power-assert-context-reducer-ast"
],
"_resolved": "https://registry.npmjs.org/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz",
"_shasum": "f2ee1f3228a90eead1245f9ab1922eb2e71d336b",
"_spec": "acorn-es7-plugin@^1.0.12",
"_where": "C:\\Users\\jlevi\\Downloads\\tr2022-strategy-master\\tr2022-strategy-master\\data analysis\\functions\\node_modules\\power-assert-context-reducer-ast",
"author": {
"name": "matatbread"
},
"bugs": {
"url": "https://github.com/MatAtBread/acorn-es7-plugin/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "A plugin for the Acorn parser that understands the ES7 keywords async and await",
"homepage": "https://github.com/MatAtBread/acorn-es7-plugin#readme",
"keywords": [
"acorn",
"parser",
"es7",
"async",
"await"
],
"license": "MIT",
"main": "acorn-es7-plugin.js",
"name": "acorn-es7-plugin",
"repository": {
"type": "git",
"url": "git+https://github.com/MatAtBread/acorn-es7-plugin.git"
},
"scripts": {
"test": "cd test ; npm i ; npm test"
},
"version": "1.1.7"
}

View File

@@ -0,0 +1,13 @@
'use strict';
try {
// If this doesn't throw, then arrow functions are supported natively.
// Do not require babel (for speed).
eval('var x = () => {};');
} catch (e) {
require('babel-core/register')({
only: /test.js$/,
presets: ['es2015']
});
}

View File

@@ -0,0 +1 @@
--compilers js:babel.js

View File

@@ -0,0 +1,42 @@
{
"name": "acorn-es7-plugin-test",
"version": "0.0.5",
"description": "Tests for acorn-es7-plugin",
"main": "nothing-here",
"scripts": {
"test": "npm i acorn@3 ; mocha --opts ./mocha.opts ; node test-es5.js ; npm i acorn@4 ; mocha --opts ./mocha.opts ; node test-es5.js ; npm i acorn@5 ; mocha --opts ./mocha.opts ; node test-es5.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/MatAtBread/acorn-es7-plugin.git"
},
"keywords": [
"acorn",
"parser",
"es7",
"async",
"await"
],
"author": "matatbread",
"license": "MIT",
"bugs": {
"url": "https://github.com/MatAtBread/acorn-es7-plugin/issues"
},
"homepage": "https://github.com/MatAtBread/acorn-es7-plugin#readme",
"devDependencies": {
"babel-core": "^6.0.20",
"babel-preset-es2015": "^6.0.15",
"estraverse": "^4.1.1",
"mocha": "^2.3.3",
"colors": "^1.1.2",
"xtend": "^4.0.1"
},
"dependencies": {
"babel-core": "^6.14.0",
"babel-preset-es2015": "^6.14.0",
"colors": "^1.1.2",
"estraverse": "^4.2.0",
"mocha": "^2.5.3",
"xtend": "^4.0.1"
}
}

View File

@@ -0,0 +1,396 @@
'use strict';
/* Simple test script that doesn't need mocha or similar - it just parses stuff and checks the returned AST */
var acorn = require('acorn');
var colors = require('colors');
require('../')(acorn);
function parse(code, pluginOptions, scriptType) {
if (Array.isArray(code)) {
code = code.join('\n');
}
return acorn.parse(code, {
sourceType: scriptType,
ecmaVersion: 8,
locations: true,
ranges: true,
plugins: {
asyncawait: pluginOptions || {}
}
});
}
function isIdentThenFnDecl(ast) {
return ast.body[0].type === 'ExpressionStatement' && ast.body[0].expression.type === 'Identifier' && ast.body[0].expression.name === 'async' && !ast.body[1].async === true && ast.body[1].type == "FunctionDeclaration";
}
function isAsyncFnDecl(ast) {
return ast.body[0].async === true && ast.body[0].type === "FunctionDeclaration";
}
function isAsyncFnExpr(ast) {
return ast.body[0].expression.async === true && ast.body[0].expression.type === "ArrowFunctionExpression";
}
function isExprType(type) {
return function (ast, sourceType) {
return ast.body[0].type === 'ExpressionStatement' && ast.body[0].expression.type === type;
};
}
var tests = [
/* Standard behaviours */
{
desc: "Simple async function",
code: "async function x() { return undefined; }",
pass: function (ast) {
return ast.body[0].async === true;
}
},{
desc: "Simple async function expression",
code: "(async function (){ })",
pass: function (ast) {
return ast.body[0].expression.async === true;
}
},{
desc: "Async function expression call (1)",
code: "(async function (){ }())",
pass: function (ast) {
return ast.body[0].expression.callee.async === true;
}
},{
desc: "Async function expression call (2)",
code: "(async function (){ })()",
pass: function (ast) {
return ast.body[0].expression.callee.async === true;
}
},{
desc: "Await in async is AwaitExpression",
code: "async function x() { await(undefined); await undefined ; }",
pass: function (ast) {
return ast.body[0].body.body[0].expression.type === 'AwaitExpression' && ast.body[0].body.body[1].expression.type === 'AwaitExpression';
}
},{
desc: "Await in function is identifier in 'script', illegal in 'module'",
code: "function x() { await(undefined); }",
pass: function (ast,scriptType) {
return scriptType === 'script'?ast.body[0].body.body[0].expression.callee.name === 'await':ast.indexOf("(1:15)")>=0;
}
},{
desc: "Async method {code}",
code: "var a = {async x(){}}",
pass: function (ast) {
return ast.body[0].declarations[0].init.properties[0].value.async;
}
},{
desc: "Async arrow",
code: "var a = async()=>0",
pass: function (ast) {
return ast.body[0].declarations[0].init.async;
}
},{
desc: "Abbreviated async arrow",
code: "var a = async b=>-b",
pass: function (ast) {
return ast.body[0].declarations[0].init.async;
}
},{
desc: "Parenthesized async arrow is a call",
code: "var a = async(b=>0)",
pass: function (ast) {
return ast.body[0].declarations[0].init.type==='CallExpression';
}
},{
desc: "Await declaration fails in async function",
code: "async function x() { var await; }",
pass: function (ex, scriptType) {
return ex.indexOf("(1:25)")>=0
}
},{
desc: "Await function declaration fails in async function",
code: "async function x() { function await() {} }",
pass: function (ex, scriptType) {
return ex.indexOf("(1:30)")>=0
}
},{
desc: "Await reference fails in async function",
code: "async function x() { return 1+await; }",
pass: function (ex) {
return !!ex.match(/\(1:3[05]\)/);
}
},{
desc: "{code} is an async FunctionExpression",
code: "async ()=>0",
pass: isAsyncFnExpr
},{
desc: "{code} is a CallExpression",
code: "async(()=>0)",
pass: isExprType('CallExpression')
},{
desc: "{code} is an async FunctionDeclaration",
code: "async /* a */ function x(){}",
pass: isAsyncFnDecl
},{
desc: "{code} is a reference to 'async' and a sync FunctionDeclaration",
code: "async /*\n*/function x(){}",
pass: isIdentThenFnDecl
},{
desc: "{code} is a reference to 'async' and a sync FunctionDeclaration",
code: "async /* a */\nfunction x(){}",
pass: isIdentThenFnDecl
},{
desc: "{code} is a reference to 'async' and a sync FunctionDeclaration",
code: "async\nfunction x(){}",
pass: isIdentThenFnDecl
},{
desc: "{code} is a reference to 'async' and a sync FunctionDeclaration",
code: "async //\nfunction x(){}",
pass: isIdentThenFnDecl
},{
desc: "{code} is a reference to 'async' and a sync FunctionDeclaration",
code: "async /*\n*/\nfunction x(){}",
pass: isIdentThenFnDecl
},{
desc: "{code} is a SyntaxError (when inAsyncFunction and awaitAnywhere option are defaults)",
code: "await x",
pass: function (ex, sourceType) {
return sourceType==='module' ? !!ex.match(/\(1:0\)/) : ex === "Unexpected token (1:6)";
}
},{
desc: "{code} is a CallExpression in scripts, and a SyntaxError in modules",
code: "await(x)",
pass: function(ast,sourceType) {
return sourceType==='module'?!!ast.match(/\(1:0\)/) :isExprType('CallExpression')(ast)
}
},{
desc: "Async method 'constructor' is valid",
code: "var a = {async constructor(){}}",
pass: function (ast) {
var props = ast.body[0].declarations[0].init.properties ;
return (props[0].kind === 'init' && props[0].key.name==='constructor' && props[0].value.async)
}
},{
desc: "Async class constructor fails",
code: "class a {async constructor(){}}",
pass: function (ex) {
return !!ex.match(/class constructor\(\) cannot be be async \(1:(15|9)\)/) || ex === "Constructor can't be an async method (1:15)";
}
},{
desc: "Async setter fails",
code: "var a = {async set x(y){}}",
pass: function (ex) {
return ex === "'set <member>(value)' cannot be be async (1:15)" || ex === "Unexpected token (1:19)";
}
},{
desc: "Deprecated async setter fails (use 'async set x')",
code: "var a = {set async x(y){}}",
pass: function (ex) {
return ex === "'set <member>(value)' cannot be be async (1:13)" || ex === "Unexpected token (1:19)";
}
},{
desc: "{code} getters/setters are not async",
code: "var a = {get x(){},set y(z){}}",
pass: function (ast) {
var props = ast.body[0].declarations[0].init.properties ;
return (props[0].kind === 'get' && props[0].key.name==='x' && !props[0].value.async)
&& (props[1].kind === 'set' && props[1].key.name==='y' && !props[1].value.async);
}
},{
desc: "{code} are methods, not getters/setters",
code: "var a = {async get(){},async set(){}}",
pass: function (ast) {
var props = ast.body[0].declarations[0].init.properties ;
return (props[0].kind === 'init' && props[0].key.name==='get' && props[0].value.async)
&& (props[1].kind === 'init' && props[1].key.name==='set' && props[1].value.async);
}
},{
desc: "In {code}, x is an sync getter",
code: "class a {get x(){}}",
pass: function (ast) {
return ast.body[0].body.body[0].kind==="get" && !ast.body[0].body.body[0].value.async && !ast.body[0].body.body[0].static ;
}
},{
desc: "In {code}, x is an static sync getter",
code: "class a {static get x(){}}",
pass: function (ast) {
return ast.body[0].body.body[0].kind==="get" && !ast.body[0].body.body[0].value.async && ast.body[0].body.body[0].static ;
}
},{
desc: "In {code}, x is an static sync method",
code: "class a {static async x(){}}",
pass: function (ast) {
return ast.body[0].body.body[0].kind==="method" && ast.body[0].body.body[0].value.async && ast.body[0].body.body[0].static ;
}
},{
desc: "{code} are a getters/setters, not methods",
code: "var a = {get async(){},set async(x){}}",
pass: function (ast) {
var props = ast.body[0].declarations[0].init.properties ;
return (props[0].kind === 'get' && props[0].key.name==='async' && !props[0].value.async)
&& (props[1].kind === 'set' && props[1].key.name==='async' && !props[1].value.async);
}
},
/* Extended syntax behaviour for Nodent */
{
desc: "Nodent:".grey+" In {code}, get is a static method",
code: "class Foo { static get(v) {} }",
pass: function (ast) {
return ast.body[0].body.body[0].type==='MethodDefinition'
&& ast.body[0].body.body[0].key.name === 'get'
&& ast.body[0].body.body[0].kind === "method"
&& ast.body[0].body.body[0].static;
}
},{
desc: "Nodent:".grey+" In {code}, get is a non-static method",
code: "class Foo { get(v) {} }",
pass: function (ast) {
return ast.body[0].body.body[0].type==='MethodDefinition'
&& ast.body[0].body.body[0].key.name === 'get'
&& ast.body[0].body.body[0].kind === "method"
&& !ast.body[0].body.body[0].static;
}
},{
desc: "Nodent:".grey+" In {code}, get is a non-static getter",
code: "class Foo { get get() {} }",
pass: function (ast) {
return ast.body[0].body.body[0].type==='MethodDefinition'
&& ast.body[0].body.body[0].key.name === 'get'
&& ast.body[0].body.body[0].kind === "get"
&& !ast.body[0].body.body[0].static;
}
},{
desc: "Nodent:".grey+" In {code}, x is an async getter",
code: "var a = {async get x(){ await(0) }}",
pass: function (ast) {
return ast.body[0].declarations[0].init.properties[0].value.async
&& ast.body[0].declarations[0].init.properties[0].value.body.body[0].expression.type==='AwaitExpression';
}
},{
desc: "Nodent:".grey+" In {code} (deprecated), x is an async getter",
code: "var a = {get async x(){ await 0 }}",
pass: function (ast) {
return ast.body[0].declarations[0].init.properties[0].value.async
&& ast.body[0].declarations[0].init.properties[0].value.body.body[0].expression.type==='AwaitExpression';
}
},{
desc: "Nodent:".grey+" In {code} (deprecated), x is an async getter",
code: "var a = {get async x(){ await(0) }}",
pass: function (ast) {
return ast.body[0].declarations[0].init.properties[0].value.async
&& ast.body[0].declarations[0].init.properties[0].value.body.body[0].expression.type==='AwaitExpression';
}
},{
desc: "Nodent:".grey+" In {code}, x is an async getter",
code: "class a {async get x(){ await 0 }}",
pass: function (ast) {
return ast.body[0].body.body[0].value.async
&& ast.body[0].body.body[0].value.body.body[0].expression.type==='AwaitExpression';
}
},{
desc: "Nodent:".grey+" In {code}, x is an async getter",
code: "class a {async get x(){ await(0) }}",
pass: function (ast) {
return ast.body[0].body.body[0].value.async
&& ast.body[0].body.body[0].value.body.body[0].expression.type==='AwaitExpression';
}
},{
desc: "Nodent:".grey+" In {code} (deprecated), x is an async getter",
code: "class a {get async x(){ await 0 }}",
pass: function (ast) {
return ast.body[0].body.body[0].value.async
&& ast.body[0].body.body[0].value.body.body[0].expression.type==='AwaitExpression';
}
},{
desc: "Nodent:".grey+" In {code} (deprecated), x is an async getter",
code: "class a {get async x(){ await(0) }}",
pass: function (ast) {
return ast.body[0].body.body[0].value.async
&& ast.body[0].body.body[0].value.body.body[0].expression.type==='AwaitExpression';
}
},{
desc: "Nodent:".grey+" In {code}, x is an static async getter",
code: "class a {static async get x(){}}",
pass: function (ast) {
return ast.body[0].body.body[0].kind==="get" && ast.body[0].body.body[0].value.async && ast.body[0].body.body[0].static ;
}
},{
desc: "Nodent:".grey+" In {code} (deprecated), x is an static async getter",
code: "class a {static get async x(){}}",
pass: function (ast) {
return ast.body[0].body.body[0].kind==="get" && ast.body[0].body.body[0].value.async && ast.body[0].body.body[0].static ;
}
},{
desc: "Nodent:".grey+" {code} is an AwaitExpression when inAsyncFunction option is true",
code: "await(x)",
options: {
inAsyncFunction: true
},
pass: isExprType('AwaitExpression')
},{
desc: "Nodent:".grey+" {code} is an AwaitExpression when inAsyncFunction option is true",
code: "await x",
options: {
inAsyncFunction: true
},
pass: isExprType('AwaitExpression')
},{
desc: "Nodent:".grey+" {code} is a CallExpression when awaitAnywhere option is true",
code: "await(x)",
options: {
awaitAnywhere: true
},
pass: isExprType('CallExpression')
},{
desc: "Nodent:".grey+" {code} is an AwaitExpression when awaitAnywhere option is true",
code: "await x",
options: {
awaitAnywhere: true
},
pass: isExprType('AwaitExpression')
}];
// TODO: Add tests for asyncExits, noAsyncGetters
var out = {
true: "pass".green,
false: "fail".red
};
var testNumber = +process.argv[2] || 0;
if (testNumber) {
tests = [tests[testNumber - 1]];
} else {
testNumber += 1;
}
var results = {
true: 0,
false: 0
};
tests.forEach(function (test, idx) {
['script','module'].forEach(function(scriptType){
var code = test.code.replace(/\n/g, ' <linefeed> ');
var desc = test.desc.replace('{code}', code.yellow);
var pass = function () {
var p = test.pass.apply(this, arguments);
results[p] += 1;
return p;
};
var prefix = idx + testNumber + " (" + scriptType + ", acorn v" + acorn.version+")\t" ;
try {
console.log(prefix, desc, out[pass(parse(test.code, test.options, scriptType),scriptType)]);
} catch (ex) {
try {
console.log(prefix, desc, ex.message.cyan, out[pass(ex.message,scriptType)]);
} catch (ex) {
console.log(prefix, desc, ex.message.magenta, out[false]);
results.false += 1;
}
}
});
}) ;
console.log('');
if (results.true)
console.log((results.true + " of " + tests.length*2 + " tests passed").green);
if (results.false) {
console.log((results.false + " of " + tests.length*2 + " tests failed").red);
var exit = new Error("Test failed") ;
exit.stack = "" ;
throw exit ;
}

View File

@@ -0,0 +1,590 @@
'use strict';
var acorn = require('acorn');
require('../')(acorn);
var estraverse = require('estraverse');
var xtend = require('xtend');
var assert = require('assert');
function find (type, ast, skip) {
skip = skip || 0;
var skipped = 0;
var found;
estraverse.traverse(ast, {
enter: (node) => {
if (found) {
return estraverse.VisitorOption.Skip;
}
if (node.type == type) {
if (skipped === skip) {
found = node;
return estraverse.VisitorOption.Skip;
}
skipped++;
}
}
});
if (!found) {
throw new Error('did not find AwaitExpression (skipped ' + skipped + '/' + skip + ')');
}
return found;
}
function extendOptions(pluginOptions, acornOptions) {
return xtend({
sourceType: 'module',
ecmaVersion: 8,
locations: true,
ranges: true,
plugins: {asyncawait: pluginOptions || pluginOptions !== false}
}, acornOptions);
}
function parse(code, pluginOptions, acornOptions) {
if (Array.isArray(code)) {
code = code.join('\n');
}
var options = extendOptions(pluginOptions, acornOptions);
return acorn.parse(code, options);
}
describe('async', () => {
describe ('function declaration', () => {
var node;
describe('-', () => {
beforeEach(() => {
node = find(
'FunctionDeclaration',
parse([
'async function foo() {',
' x = await bar()',
'}'
])
);
});
it('marks the node as async', () =>
assert(node.async)
);
it('finds correct start position', () =>
assert.strictEqual(node.start, 0)
);
it('finds correct end position', () =>
assert.strictEqual(node.end, 42)
);
it('finds correct start line/column', () =>
assert.deepEqual(node.loc.start, {
line: 1,
column: 0
})
);
it('finds correct end line/column', () =>
assert.deepEqual(node.loc.end, {
line: 3,
column: 1
})
);
});
var assertFindsIdentifierExpressionStatement = (ast) => {
node = find('ExpressionStatement', ast);
assert.strictEqual(node.expression.type, 'Identifier');
assert.strictEqual(node.expression.name, 'async');
assert.deepEqual(node.expression.loc, {
start: {
line: 1,
column: 0
},
end: {
line: 1,
column: 5
}
});
};
describe('linefeed after async (simple)', () => {
var ast;
beforeEach(() => {
ast = parse([
'async \t\t ',
'function foo() {',
'}'
]);
});
it('finds Identifier ExpressionStatement', () => {
assertFindsIdentifierExpressionStatement(ast);
});
it('does not mark FunctionDeclaration as async', () => {
node = find('FunctionDeclaration', ast);
assert(!node.async, 'Expected node.async to be false');
});
});
describe('linefeed after async (single line comment)', () => {
var ast;
beforeEach(() => {
ast = parse([
'async // flag enables async completion',
'function foo() {',
'}'
]);
});
it('finds Identifier ExpressionStatement', () => {
assertFindsIdentifierExpressionStatement(ast);
});
it('does not mark FunctionDeclaration as async', () => {
node = find('FunctionDeclaration', ast);
assert(!node.async, 'Expected node.async to be false');
});
});
describe('linefeed after async (multiline comment) function', () => {
var ast;
beforeEach(() => {
ast = parse([
'async /* flag enables async completion',
' of the callback */function foo() {',
'}'
]);
});
it('finds Identifier ExpressionStatement', () => {
assertFindsIdentifierExpressionStatement(ast);
});
it('does not mark FunctionDeclaration as async', () => {
node = find('FunctionDeclaration', ast);
assert(!node.async, 'Expected node.async to be false');
});
});
});
describe ('function expression', () => {
var node, code;
describe('-', () => {
beforeEach(() => {
code = [
'foo = async function () {',
' x = await bar()',
'}'
];
node = find(
'FunctionExpression',
parse(code)
);
});
it('marks the node as async', () =>
assert(node.async)
);
it('finds correct start position', () =>
assert.strictEqual(node.start, 6)
);
it('finds correct end position', () =>
assert.strictEqual(node.end, code.join('\n').length)
);
it('finds correct start line/column', () =>
assert.deepEqual(node.loc.start, {
line: 1,
column: 6
})
);
it('finds correct end line/column', () =>
assert.deepEqual(node.loc.end, {
line: 3,
column: 1
})
);
});
var assertFindsIdentifierAssignmentExpressionRHS = (ast) => {
node = find('AssignmentExpression', ast);
assert.strictEqual(node.right.type, 'Identifier');
assert.strictEqual(node.right.name, 'async');
assert.deepEqual(node.right.loc, {
start: {
line: 1,
column: 6
},
end: {
line: 1,
column: 11
}
});
};
describe('linefeed after async (simple)', () => {
var ast;
beforeEach(() => {
ast = parse([
'foo = async \t\t ',
', function() {',
'}'
]);
});
it('finds Identifier ExpressionStatement', () => {
assertFindsIdentifierAssignmentExpressionRHS(ast);
});
it('does not mark FunctionExpression as async', () => {
node = find('FunctionExpression', ast);
assert(!node.async, 'Expected node.async to be false');
});
});
describe('linefeed after async (single line comment)', () => {
var ast;
beforeEach(() => {
ast = parse([
'foo = async // flag enables async completion',
', function() {',
'}'
]);
});
it('finds Identifier ExpressionStatement', () => {
assertFindsIdentifierAssignmentExpressionRHS(ast);
});
it('does not mark FunctionExpression as async', () => {
node = find('FunctionExpression', ast);
assert(!node.async, 'Expected node.async to be false');
});
});
describe('linefeed after async (multiline comment), function', () => {
var ast;
beforeEach(() => {
ast = parse([
'foo = async /* flag enables async completion',
' of the callback */, function() {',
'}'
]);
});
it('finds Identifier ExpressionStatement', () => {
assertFindsIdentifierAssignmentExpressionRHS(ast);
});
it('does not mark FunctionExpression as async', () => {
node = find('FunctionExpression', ast);
assert(!node.async, 'Expected node.async to be false');
});
});
});
describe ('enhanced object literal', () => {
var node, code;
describe('-', () => {
beforeEach(() => {
code = [
'var x = {',
' async foo() {}',
'};'
];
node = find(
// TODO: Is it really supposed to mark the Property async? Why not the FunctionExpression?
'Property',
parse(code)
);
});
it('marks the node value as async', () =>
assert(node.value.async)
);
it('does not mark the node as async', () =>
assert(!node.async)
);
it('finds correct start position', () =>
assert.strictEqual(node.start, 12)
);
it('finds correct end position', () =>
assert.strictEqual(node.end, code[0].length + code[1].length + 1) // + 1 is due to newline char
);
it('finds correct start line/column', () =>
assert.deepEqual(node.loc.start, {
line: 2,
column: 2
})
);
it('finds correct end line/column', () =>
assert.deepEqual(node.loc.end, {
line: 2,
column: 16
})
);
});
describe('linefeed after async (simple)', () => {
it('fails to parse', () => {
assert.throws(() => parse([
'var x = {',
' async \t\t ',
' foo() {}',
'};'
]));
});
});
describe('linefeed after async (single line comment)', () => {
it('fails to parse', () => {
assert.throws(() => parse([
'var x = {',
' async // flag enables async completion',
' foo() {}',
'};'
]));
});
});
describe('linefeed after async (multiline comment) illegal decl', () => {
it('finds Identifier ExpressionStatement', () => {
assert.throws(() => parse([
'var x = {',
' async /* flag enables async completion',
' of the callback */ foo() {}',
'};'
]));
});
});
});
describe ('ArrowFunctionExpression', () => {
var node, code;
describe('-', () => {
beforeEach(() => {
code = 'var x = async () => {}';
node = find(
'ArrowFunctionExpression',
parse(code)
);
});
it('marks the node as async', () =>
assert(node.async)
);
it('finds correct start position', () =>
assert.strictEqual(node.start, 8)
);
it('finds correct end position', () =>
assert.strictEqual(node.end, code.length)
);
it('finds correct start line/column', () =>
assert.deepEqual(node.loc.start, {
line: 1,
column: 8
})
);
it('finds correct end line/column', () =>
assert.deepEqual(node.loc.end, {
line: 1,
column: code.length
})
);
});
describe('linefeed after async (simple)', () => {
var ast;
beforeEach(() => {
ast = parse([
'var x = async \t\t ',
'()'
]);
});
it('fails to parse if linefeed preceeds arrow arguments', () => {
assert.throws(() => parse([
'var x = async \t\t ',
'() => {}'
]));
});
it('finds CallExpression with "async" Identifier callee', () => {
node = find('CallExpression', ast);
assert.strictEqual(node.callee.type, 'Identifier');
assert.strictEqual(node.callee.name, 'async');
assert.deepEqual(node.callee.loc, {
start: {
line: 1,
column: 8
},
end: {
line: 1,
column: 13
}
});
});
});
describe('linefeed after async (single line comment)', () => {
var ast;
beforeEach(() => {
ast = parse([
'var x = async // flag enables async completion',
'()'
]);
});
it('fails to parse if linefeed preceeds arrow arguments', () => {
assert.throws(() => parse([
'var x = async \t\t ',
'() => {}'
]));
});
it('finds CallExpression with "async" Identifier callee', () => {
node = find('CallExpression', ast);
assert.strictEqual(node.callee.type, 'Identifier');
assert.strictEqual(node.callee.name, 'async');
assert.deepEqual(node.callee.loc, {
start: {
line: 1,
column: 8
},
end: {
line: 1,
column: 13
}
});
});
});
describe('linefeed after async (multiline comment) arrow decl', () => {
var ast;
beforeEach(() => {
ast = parse([
'var x = async /* flag enables async completion',
' of the callback */()'
]);
});
it('fails to parse if linefeed preceeds arrow arguments', () => {
assert.throws(() => parse([
'var x = async /* flag enables async completion',
' of the callback */() => {}'
]));
});
it('finds CallExpression with "async" Identifier callee', () => {
node = find('CallExpression', ast);
assert.strictEqual(node.callee.type, 'Identifier');
assert.strictEqual(node.callee.name, 'async');
assert.deepEqual(node.callee.loc, {
start: {
line: 1,
column: 8
},
end: {
line: 1,
column: 13
}
});
});
});
});
});
describe('await', () => {
describe('-', () => {
var node;
beforeEach(() => {
node = find(
'AwaitExpression',
parse([
'async function foo() {',
' x = await bar()',
'}'
])
);
});
it('finds correct start position', () =>
assert.strictEqual(node.start, 29)
);
it('finds correct end position', () =>
assert.strictEqual(node.end, 40)
);
it('finds correct start line/column', () =>
assert.deepEqual(node.loc.start, {
line: 2,
column: 6
})
);
it('finds correct end line/column', () =>
assert.deepEqual(node.loc.end, {
line: 2,
column: 17
})
);
});
describe('outside a function (awaitAnywhere)', () => {
var node;
beforeEach(() => {
node = find(
'AwaitExpression',
parse(
'x = await bar()',
{awaitAnywhere:true}
)
);
});
it('finds correct start position', () =>
assert.strictEqual(node.start, 4)
);
it('finds correct start line/column', () =>
assert.deepEqual(node.loc.start, {
line: 1,
column: 4
})
);
it('finds correct end position', () =>
assert.strictEqual(node.end, 15)
);
it('finds correct end line/column', () =>
assert.deepEqual(node.loc.end, {
line: 1,
column: 15
})
);
});
});

View File

@@ -0,0 +1,15 @@
(function () {
"use strict";
const acorn = require('acorn'); // 3.x
require('..')(acorn);
var code = "(async function x(){ console.log('hello'); }());";
var ast = acorn.parse(code,{
// Specify use of the plugin
plugins:{asyncawait:true},
// Specify the ecmaVersion
ecmaVersion: 7
}) ;
// Show the AST
console.log(JSON.stringify(ast,null,2)) ;
}());