You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

591 lines
14 KiB
JavaScript

'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
})
);
});
});