Skip to content

[Bug]: TypeError: traverse is not a function when using @babel/traverse in node.js #13855

@xsjcTony

Description

@xsjcTony

💻

  • Would you like to work on a fix?

How are you using Babel?

Programmatic API (@babel/traverse)

Input code

// index.mjs
import * as parser from '@babel/parser'
import traverse from '@babel/traverse'

const code = `function square(n) {
  return n * n;
}`

const ast = parser.parse(code)

traverse(ast, {
  enter (path) {
    console.log(path.node.type)
  }
})

Configuration file name

No response

Configuration

No response

Current and expected behavior

I'm using the same code example as in @babel/traverse doc page: @babel/traverse - Babel
all outputs below are the same if I use CommonJS import instead of ESM import

const parser = require('@babel/parser')
const traverse = require('@babel/traverse')

The same thing happens to @babel/generator as well


Current output in the shell:

G:\NodeJS\node.exe D:\xsjcTony\Aelita\test.mjs
file:///D:/xsjcTony/Aelita/test.mjs:10
traverse(ast, {
^

TypeError: traverse is not a function
    at file:///D:/xsjcTony/Aelita/test.mjs:10:1
    at ModuleJob.run (internal/modules/esm/module_job.js:183:25)
    at async Loader.import (internal/modules/esm/loader.js:178:24)
    at async Object.loadESM (internal/process/esm_loader.js:68:5)

Process finished with exit code 1

The expected output in the shell:

G:\NodeJS\node.exe D:\xsjcTony\Aelita\test.js
Program
FunctionDeclaration
Identifier
Identifier
BlockStatement
ReturnStatement
BinaryExpression
Identifier
Identifier

Process finished with exit code 0

Environment

All packages are installed by npm with the default latest version

  • @babel/core: 7.15.8
  • @babel/parser: 7.15.8
  • @babel/traverse: 7.15.4
  • node: v14.18.0
  • npm: 7.24.2
  • OS: Windows 10

Possible solution

The solution is just to use @babel/core.traverse instead or use traverse.default(ast, {}).
But I'm confused why this happens when I'm 100% following the example code in documentation.
I have had a look at files inside the package and I found the following in ./node_modules/@babel/traverse/lib/index.js

function traverse(parent, opts = {}, scope, state, parentPath) {
  if (!parent) return;

  if (!opts.noScope && !scope) {
    if (parent.type !== "Program" && parent.type !== "File") {
      throw new Error("You must pass a scope and parentPath unless traversing a Program/File. " + `Instead of that you tried to traverse a ${parent.type} node without ` + "passing scope and parentPath.");
    }
  }

  if (!VISITOR_KEYS[parent.type]) {
    return;
  }

  visitors.explode(opts);
  traverse.node(parent, opts, scope, state, parentPath);
}

var _default = traverse;
exports.default = _default;
traverse.visitors = visitors;
traverse.verify = visitors.verify;
traverse.explode = visitors.explode;

where exports.default is the traverse function and that's why I found traverse.default(ast, {}) works.
I'm a newbie to JavaScript but in my opinion, it should be either export default _default or module.exports = _default to make the code in documentation work?

Additional context

Well, this is my first time raising an issue and hopefully, it's not a dumb one. ^_^

Metadata

Metadata

Assignees

No one assigned

    Labels

    outdatedA 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