Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Maximum call stack size exceeded when building lib via babel CLI (T7402) #4323

Closed
babel-bot opened this issue Jun 1, 2016 · 3 comments · Fixed by #5235
Closed

Maximum call stack size exceeded when building lib via babel CLI (T7402) #4323

babel-bot opened this issue Jun 1, 2016 · 3 comments · Fixed by #5235
Labels
Has PR outdated A closed issue/PR that is archived due to age. Recommended to make a new issue

Comments

@babel-bot
Copy link
Collaborator

Issue originally made by @nathanmarks

Bug information

  • Babel version: 6.9.0
  • Node version: 5.11.1
  • npm version: 3.8.6

Input code

https://github.com/callemall/material-ui

`npm install`
`npm run build:babel`

Description

Encountering the following error when trying to build the following lib: https://github.com/callemall/material-ui

RangeError: src/svg-icons/index.js: Maximum call stack size exceeded
    at CodeGenerator.Identifier (./node_modules/babel-generator/lib/generators/types.js:33:20)
    at CodeGenerator._print (./node_modules/babel-generator/lib/printer.js:184:17)
    at ./node_modules/babel-generator/lib/printer.js:120:38
    at CodeGenerator.withSource (./node_modules/babel-generator/lib/buffer.js:279:5)
    at CodeGenerator.print (./node_modules/babel-generator/lib/printer.js:119:10)
    at CodeGenerator.MemberExpression (./node_modules/babel-generator/lib/generators/expressions.js:243:8)
    at CodeGenerator._print (./node_modules/babel-generator/lib/printer.js:184:17)
    at ./node_modules/babel-generator/lib/printer.js:120:38
    at CodeGenerator.withSource (./node_modules/babel-generator/lib/buffer.js:279:5)
    at CodeGenerator.print (./node_modules/babel-generator/lib/printer.js:119:10)

Reproducible by doing:

npm install
npm run build:babel

Note: When I break down the build process and build a smaller set of files, say, just the svg-icons folder, it works fine. But when I try build the entire lib with a single command, I get a stack overflow at the same point in the build process every single time.

@babel-bot
Copy link
Collaborator Author

Comment originally made by @loganfsmyth

Okay, I've tracked down the cause of this.

Given content like

export Foo1 from 'foo1';
export Foo2 from 'foo2';
export Foo3 from 'foo3';
export Foo4 from 'foo4';
export Foo5 from 'foo5';
export Foo6 from 'foo6';

we currently generate:

'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.Foo6 = exports.Foo5 = exports.Foo4 = exports.Foo3 = exports.Foo2 = exports.Foo1 = undefined;

var _foo = require('foo1');

var _foo2 = _interopRequireDefault(_foo);

var _foo3 = require('foo2');

var _foo4 = _interopRequireDefault(_foo3);

var _foo5 = require('foo3');

var _foo6 = _interopRequireDefault(_foo5);

var _foo7 = require('foo4');

var _foo8 = _interopRequireDefault(_foo7);

var _foo9 = require('foo5');

var _foo10 = _interopRequireDefault(_foo9);

var _foo11 = require('foo6');

var _foo12 = _interopRequireDefault(_foo11);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

exports.Foo1 = _foo2.default;
exports.Foo2 = _foo4.default;
exports.Foo3 = _foo6.default;
exports.Foo4 = _foo8.default;
exports.Foo5 = _foo10.default;
exports.Foo6 = _foo12.default;

The problem in this case is this line:

exports.Foo6 = exports.Foo5 = exports.Foo4 = exports.Foo3 = exports.Foo2 = exports.Foo1 = undefined;

which when you get to a file like this: https://github.com/callemall/material-ui/blob/cbf3280ee58fed33c4ef12e62d00d09ac35fd087/src/svg-icons/index.js gives you nearly 1000 nested assignment nodes in the AST. Then when you multiply that by the fact that each call to generate the child assignment via the generator introduces not just one but several new stack frames, means that we get a pretty call sizable stack.

The quickest fix for this would probably be split this assignment into groups once you past a certain number of exports being assigned. This issue was also probably excacerbated by #3463 which introduced an extra stack frame per call, so another alternative would probably be to replace withSource with a startSource() and endSource(), but we'd need to check performance around that because it could end up hurting codegen times.

@mattste
Copy link
Contributor

mattste commented Jan 26, 2017

It appears this is still a problem. I have encountered this issue using material-ui in a React Native Webview. The assignment produces a stack that causes a stack overflow.

I'd be interested in tackling this if someone would lend a little guidance on what part of the codebase to look into.

@loganfsmyth
Copy link
Member

Feel free to hop on our Slack if you have questions. Essentially what we'd want to do is change this loop:

for (const name in nonHoistedExportNames) {

so that for very large sets of nonHoistedExportNames, we break the expression into multiple expression statements. Maybe we can limit each one to 100 exports?

mattste added a commit to mattste/babel that referenced this issue Jan 28, 2017
Signed-off-by: Matthew Stewart <mattdste@gmail.com>
loganfsmyth added a commit that referenced this issue Jan 28, 2017
Limit export node default assignment stack size #4323
chitchu pushed a commit to chitchu/babel that referenced this issue Jan 29, 2017
Signed-off-by: Matthew Stewart <mattdste@gmail.com>
existentialism pushed a commit that referenced this issue May 19, 2017
Signed-off-by: Matthew Stewart <mattdste@gmail.com>
@lock lock bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label May 5, 2018
@lock lock bot locked as resolved and limited conversation to collaborators May 5, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Has PR outdated A closed issue/PR that is archived due to age. Recommended to make a new issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants