123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- 'use strict';
- var parser = require('acorn');
- require('acorn-es7-plugin')(parser);
- var estraverse = require('estraverse');
- var purifyAst = require('espurify').customize({extra: ['range']});
- var assign = require('core-js/library/fn/object/assign');
- module.exports = function (powerAssertContext) {
- var source = powerAssertContext.source;
- if (source.ast && source.tokens && source.visitorKeys) {
- return powerAssertContext;
- }
- var astAndTokens;
- try {
- astAndTokens = parse(source);
- } catch (e) {
- return assign({}, powerAssertContext, { source: assign({}, source, { error: e }) });
- }
- var newSource = assign({}, source, {
- ast: purifyAst(astAndTokens.expression),
- tokens: astAndTokens.tokens,
- visitorKeys: estraverse.VisitorKeys
- });
- return assign({}, powerAssertContext, { source: newSource });
- };
- function parserOptions(tokens) {
- return {
- sourceType: 'module',
- ecmaVersion: 2018,
- locations: true,
- ranges: false,
- onToken: tokens,
- plugins: {asyncawait: true}
- };
- }
- function parse (source) {
- var code = source.content;
- var ast, tokens;
- function doParse(wrapper) {
- var content = wrapper ? wrapper(code) : code;
- var tokenBag = [];
- ast = parser.parse(content, parserOptions(tokenBag));
- if (wrapper) {
- ast = ast.body[0].body;
- tokens = tokenBag.slice(6, -2);
- } else {
- tokens = tokenBag.slice(0, -1);
- }
- }
- if (source.async) {
- doParse(wrappedInAsync);
- } else if (source.generator) {
- doParse(wrappedInGenerator);
- } else {
- doParse();
- }
- var exp = ast.body[0].expression;
- var columnOffset = exp.loc.start.column;
- var offsetTree = estraverse.replace(exp, {
- keys: estraverse.VisitorKeys,
- enter: function (eachNode) {
- if (!eachNode.loc && eachNode.range) {
- // skip already visited node
- return eachNode;
- }
- eachNode.range = [
- eachNode.loc.start.column - columnOffset,
- eachNode.loc.end.column - columnOffset
- ];
- delete eachNode.loc;
- return eachNode;
- }
- });
- return {
- tokens: offsetAndSlimDownTokens(tokens),
- expression: offsetTree
- };
- }
- function wrappedInGenerator (jsCode) {
- return 'function *wrapper() { ' + jsCode + ' }';
- }
- function wrappedInAsync (jsCode) {
- return 'async function wrapper() { ' + jsCode + ' }';
- }
- function offsetAndSlimDownTokens (tokens) {
- var i, token, newToken, result = [];
- var columnOffset;
- for(i = 0; i < tokens.length; i += 1) {
- token = tokens[i];
- if (i === 0) {
- columnOffset = token.loc.start.column;
- }
- newToken = {
- type: {
- label: token.type.label
- }
- };
- if (typeof token.value !== 'undefined') {
- newToken.value = token.value;
- }
- newToken.range = [
- token.loc.start.column - columnOffset,
- token.loc.end.column - columnOffset
- ];
- result.push(newToken);
- }
- return result;
- }
|