Skip to content

Babel AST transform drops Recast's original property #12882

@NickHeiner

Description

@NickHeiner

Bug Report

Maybe you don't consider this a bug, but I thought I'd flag it anyway.

Current behavior
Recast (0.20.4) works by attaching an original property to AST nodes. babel.transformFromAst drops that property, preventing Recast from working as expected.

This is demonstrated by the following script:

const babel = require('@babel/core');
const recast = require('recast');
const _ = require('lodash');

const filename = 'file.js';
const source = `
function f(
  a,
  b,
  c
) {
  return d;
}
`;

const babelOpts = {
  filename,
  ast: true
};

const parser = {
  parse(source, opts) {
    return babel.parse(source, {
      ...babelOpts,
      ..._.omit(
        opts, 
        'jsx', 'loc', 'locations', 'range', 'comment', 'onComment', 'tolerant', 'ecmaVersion'
      )
    });
  }
};

const ast = recast.parse(source, {parser});
const result = babel.transformFromAstSync(ast, source, babelOpts);

const printedFromRecastParse = recast.print(ast).code;
const printedFromBabelTransform = recast.print(result.ast).code;

console.log('printedFromRecastParse', printedFromRecastParse);
console.log();
console.log('printedFromBabelTransform', printedFromBabelTransform);

This produces:

printedFromRecastParse
function f(
  a,
  b,
  c
) {
  return d;
}


printedFromBabelTransform "use strict";
function f(a, b, c) {
  return d;
}

Expected behavior
Program output:

printedFromRecastParse
"use strict";
function f(
  a,
  b,
  c
) {
  return d;
}


printedFromBabelTransform "use strict";
function f(
  a,
  b,
  c
) {
  return d;
}

Environment

  System:
    OS: macOS 11.2.1
  Binaries:
    Node: 12.14.0 - ~/.nvm/versions/node/v12.14.0/bin/node
    Yarn: 1.22.5 - /usr/local/bin/yarn
    npm: 6.13.4 - ~/.nvm/versions/node/v12.14.0/bin/npm
  npmPackages:
    @babel/core: 7.13.1 => 7.13.1
    @babel/plugin-syntax-pipeline-operator: 7.12.13 => 7.12.13
    @babel/plugin-transform-typescript: 7.13.0 => 7.13.0
    @babel/preset-env: 7.11.5 => 7.11.5
    @babel/preset-typescript: 7.10.4 => 7.10.4
    babel-jest: 26.3.0 => 26.3.0
    eslint: 7.9.0 => 7.9.0
    jest: 26.4.2 => 26.4.2
  • Monorepo: no
  • How you are using Babel: Standalone

Possible Solution
This workaround addresses the issue, but it's a bit cumbersome. Here's the snippet above with the workaround applied:

const babel = require('@babel/core');
const recast = require('recast');
const _ = require('lodash');

const filename = 'file.js';
const source = `
function f(
  a,
  b,
  c
) {
  return d;
}
`;

const babelOpts = {
  filename,
  ast: true,
  code: false
};

const parser = {
  parse(source, opts) {
    return babel.parse(source, {
      ...babelOpts,
      ..._.omit(
        opts, 
        'jsx', 'loc', 'locations', 'range', 'comment', 'onComment', 'tolerant', 'ecmaVersion'
      )
    });
  }
};


const ast = recast.parse(source, {parser});

const setAst = babel => ({
  visitor: {
    Program(path) {
      path.replaceWith(ast.program);
    }
  }
});
const result = babel.transformSync('', {
  ...babelOpts,
  plugins: [setAst]
});

const printedFromRecastParse = recast.print(ast).code;
const printedFromBabelTransform = recast.print(result.ast).code;

console.log('printedFromRecastParse', printedFromRecastParse);
console.log();
console.log('printedFromBabelTransform', printedFromBabelTransform);

Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    i: needs triageoutdatedA closed issue/PR that is archived due to age. Recommended to make a new issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions