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

TypeError: Cannot read property '_walk' of null #120

Closed
joshsearles opened this issue Sep 28, 2018 · 30 comments · Fixed by #152
Closed

TypeError: Cannot read property '_walk' of null #120

joshsearles opened this issue Sep 28, 2018 · 30 comments · Fixed by #152

Comments

@joshsearles
Copy link

joshsearles commented Sep 28, 2018

Bug Report

terser v3.9.2

Building Ember js Project

Error: Build Canceled: Broccoli Builder ran into an error with `UglifyWriter` plugin. 💥
Cannot read property '_walk' of null
TypeError: Cannot read property '_walk' of null
    at AST_Node.eval (eval at <anonymous> (/usr/local/src/node_modules/terser/tools/node.js:21:1), <anonymous>:1145:28)
    at Object.TreeWalker._visit (eval at <anonymous> (/usr/local/src/node_modules/terser/tools/node.js:21:1), <anonymous>:1546:21)
    at AST_Node.DEFNODE._walk (eval at <anonymous> (/usr/local/src/node_modules/terser/tools/node.js:21:1), <anonymous>:1144:24)
    at AST_Node.eval (eval at <anonymous> (/usr/local/src/node_modules/terser/tools/node.js:21:1), <anonymous>:1091:40)
    at Object.TreeWalker._visit (eval at <anonymous> (/usr/local/src/node_modules/terser/tools/node.js:21:1), <anonymous>:1546:21)
    at AST_Node.DEFNODE._walk (eval at <anonymous> (/usr/local/src/node_modules/terser/tools/node.js:21:1), <anonymous>:1089:24)
    at AST_Node.eval (eval at <anonymous> (/usr/local/src/node_modules/terser/tools/node.js:21:1), <anonymous>:999:32)
    at Object.TreeWalker._visit (eval at <anonymous> (/usr/local/src/node_modules/terser/tools/node.js:21:1), <anonymous>:1546:21)
    at AST_Node.DEFNODE._walk (eval at <anonymous> (/usr/local/src/node_modules/terser/tools/node.js:21:1), <anonymous>:996:24)
    at walk_body (eval at <anonymous> (/usr/local/src/node_modules/terser/tools/node.js:21:1), <anonymous>:510:17)Pipeline aborted

EDIT:
to replicate on a basic ember js project (apparently it was the ember-cli-deploy plugin for me)

# npm install ember-cli-deploy
# npm install && ember deploy production
@kzc
Copy link
Contributor

kzc commented Sep 28, 2018

There is no actionable information here since you failed to fill out the issue template.

    Issues without a reproducible test case will be closed.

@fabiosantoscode
Copy link
Collaborator

Try to generate a minimal code example which fails on terser

@alechirsch
Copy link

+1, I also run into this problem, these other issues are related

angular/angular-cli#12414
ember-cli/ember-cli#8075

@kzc
Copy link
Contributor

kzc commented Oct 1, 2018

@alechirsch Without a standalone javascript example reproducing the problem nothing can be done. All the information outlined here is required:

https://raw.githubusercontent.com/terser-js/terser/master/.github/ISSUE_TEMPLATE.md

@jrjohnson
Copy link

I'm attempting to track down where this issue may fall. It did not exist in 3.8.2 and I'm seeing it in 3.9.2. Unfortunately all of these releases are on NPM, but tags have no been pushed to github. If someone can push those tags it will be much easier to investigate this issue.

@kzc
Copy link
Contributor

kzc commented Oct 1, 2018

To make a bug repro just provide the arguments passed to terser minify().

The easiest way to do that is to find the terser directory in node_modules:

find . -name terser -type d
./node_modules/terser

then remove the bundle from its dist directory:

rm -f node_modules/terser/dist/*

then go to the terser directory in node_modules and apply this patch:

--- a/lib/minify.js
+++ b/lib/minify.js
@@ -59,2 +59,4 @@ function to_json(cache) {
 function minify(files, options) {
+    console.error("*** terser options:\n", options);
+    console.error("*** terser input:\n", files);
     var warn_function = AST_Node.warn_function;

and then run npm run prepare from the terser directory to rebuild the Terser bundle.

Then you can run your project's build command as normal.

Paste the stderr output into a gist and drop the URL here in this ticket.

@jrjohnson
Copy link

Thanks, I've pasted the (huge) output into https://gist.github.com/jrjohnson/0a73a3f8588b5ced74f79530eda2a449

At the end it refers to a Stack Trace and Error Report and I put that at https://gist.github.com/jrjohnson/cf4cbcb9922d5f9a1286b41f1eaee079

@kzc
Copy link
Contributor

kzc commented Oct 1, 2018

@jrjohnson Unable to reproduce any error using terser@3.9.2 with the minify options:

 { mangle: { safari10: true },
  compress: { negate_iife: false, sequences: 30 },
  output: { semicolons: false },
  sourceMap: false }

and the (cleaned up) source from https://gist.github.com/jrjohnson/0a73a3f8588b5ced74f79530eda2a449

Strangely, the gist link above mentions an "Invalid assignment" parse error, which is different than the "Cannot read property '_walk' of null" error reported in the top post. I was not able to reproduce either error.

@jrjohnson
Copy link

jrjohnson commented Oct 1, 2018

I'm sorry @kzc I think I may have been in a rush and gotten sloppy with my original output. I've replaced the content of both gists with a correct update that is failing with the Cannot read property '_walk' of null error.

@kzc
Copy link
Contributor

kzc commented Oct 1, 2018

https://gist.github.com/jrjohnson/0a73a3f8588b5ced74f79530eda2a449/raw/2bce10e922162ec3dae635c5bd7c4b509303a4b0/output.text is corrupted.

                  return regeneratorRuntime.wrap(function _callee5$(_context5) {
                    while (1) {
                      switch (_context5.prev = _context5.next) {
                        case 0:
                 *** terser options:
 { compress: { negate_iife: false, sequences: 30 },
  mangle: { safari10: true },
  output: { semicolons: false },
  sourceMap: false }
         _context5.next = 2;
                          return program.get('school');

                        case 2:

...

  Object.defineProperty(exports, 'default', {
    enumerable: true,
    get: function () {
      return _previous.defaul*** terser input:
 window.EmberENV = {"FEATURES":{},"EXTEND_PROTOTYPES":{"String":true,"Array":true,"Function":false,"Date":false},"_APPLICATION_TEMPLATE_WRAPPER":false,"_JQUERY_INTEGRATION":true};
var runningTests = false;

You need to come up with a way to save the minify input in some other way - via fs.writeFileSync or some other means.

@kzc
Copy link
Contributor

kzc commented Oct 1, 2018

It's possible that code is being minified in parallel by ember. If so, disable this option.

@jrjohnson
Copy link

Ok, I think I've fixed it up. Went with yarn build -e production > /tmp/output 2>/tmp/error.out and then cat /tmp/error.out | pbcopy which seems to have resulted in better line breaks (in case anyone else is attempts).

@kzc
Copy link
Contributor

kzc commented Oct 2, 2018

@jrjohnson That did the trick.

Here's a reduced test case:

$ cat bug.js 
function foo(node) {
    var traverse = function(obj) {
        var i = obj.data;
        return i && i.a != i.b;
    };
    while (traverse(node)) {
        node = node.data;
    }
    return node;
}
var x = {
    a: 1,
    b: 2,
    data: {
        a: "hello",
    }
};
console.log(foo(x).a, foo({a : "world"}).a);

Expected:

$ cat bug.js | node
hello world

$ cat bug.js | terser | node
hello world

Actual:

$ cat bug.js | terser -c
ERROR: Cannot read property '_walk' of null

Recommended workaround:

Set the compress option inline to 2.

$ cat bug.js | terser -c inline=2 | node
hello world

Note: This is not a recent bug. It is present in all versions of terser as well as both uglify-es and latest uglify-js:

$ uglify-es -V
uglify-es 3.3.9

$ cat bug.js | uglify-es -c
ERROR: Cannot read property '_walk' of null
$ uglify-js -V
uglify-js 3.4.9

$ cat bug.js | uglify-js -c
ERROR: Cannot read property '_walk' of null

Issue was introduced in 9b58b54.

@kzc
Copy link
Contributor

kzc commented Oct 2, 2018

This is an interesting bug. It is caused by the interaction of the following compress options:

  • collapse_vars
  • inline=3
  • join_vars
  • loops
  • reduce_vars
  • sequences (depending on the code)
  • unused

Disabling any of those compress options will make it work. In the case of inline, a setting of 2 also works - which coincidentally produces the smallest Terser minified bundle for the large gist example.

What happens in the reduced test case is that the AST_Dot.expression obj incorrectly becomes null in var i = obj.data; in the course of one of the transforms which ultimately fails during a subsequent tree traversal:

TypeError: Cannot read property '_walk' of null
    at AST_Dot.eval 
    at TreeWalker._visit 
    at AST_Dot._walk 
    at AST_VarDef.eval 
    at TreeWalker._visit 
    at AST_VarDef._walk 
    at AST_Var.eval 
    at TreeWalker._visit 
    at AST_Var._walk 
    at walk_body 

I suspect that something in the inline=3 function cloning logic went awry in relation to the loop condition.

@kzc
Copy link
Contributor

kzc commented Oct 2, 2018

@joshsearles Could you please change the title of this issue to the following?

TypeError: Cannot read property '_walk' of null

@joshsearles joshsearles changed the title Broccoli Builder ran into an error with UglifyWriter plugin - _walk of null TypeError: Cannot read property '_walk' of null Oct 2, 2018
@joshsearles
Copy link
Author

updated @kzc

@kzc
Copy link
Contributor

kzc commented Oct 2, 2018

A similar (but unrelated) past bug and its fix might inspire some ideas for this issue.

@kzc
Copy link
Contributor

kzc commented Oct 2, 2018

@jrjohnson If you're wondering why this long-standing Terser bug just appeared in the last week, by coincidence this perfectly valid September 27th tether@1.4.5 commit was introduced as a dependency of your gist example which just happened to exercise it. Note its similarity to the reduced test case above.

I suspect any other project using tether@1.4.5 would have the same issue with Terser. If the Tether function in question were hoisted from the else clause to the top of its enclosing function it'd probably avoid the Terser bug.

$ curl -s https://raw.githubusercontent.com/HubSpot/tether/23ff7b761332313dc072df799fb15a35dde14bf4/dist/js/tether.js | terser -mc
ERROR: Cannot read property '_walk' of null

See shipshapecode/tether#291

@jrjohnson
Copy link

I figured it must be a dependency chain issue. Either either terser's deps or in the fairly vast ember build ecosystem. Thanks for digging into it so far! I've implemented the collapse_vars=false fix mentioned in some of the linked issues and I'm much happier with it as a solution now that I understand why it helps.

@fabiosantoscode
Copy link
Collaborator

fabiosantoscode commented Oct 3, 2018

Even more reduced test case:

function foo(node) {
    var traverse = function(obj) {
        var i = obj.data;
        return i && i.a != i.b;
    };
    while (traverse(node)) { }
}   

@kzc
Copy link
Contributor

kzc commented Oct 4, 2018

Even more reduced test case:

#120 (comment) is an expect_stdout test case that can be verified against a variety of minify options once the bug is fixed.

@fabiosantoscode
Copy link
Collaborator

Even more reduced test case:

const foo = function () {
    var t = function(o) {
        var i = o.b;
        i + i.a
    };
    while (t()) { }
}

@kzc
Copy link
Contributor

kzc commented Oct 4, 2018

Since we're playing code golf, here's a failure involving AST_Unary rather than AST_Dot:

$ echo 'function f(){for(var t=o=>{var i=+o;return i+i};t(););}' | terser -c
ERROR: Cannot read property '_walk' of null

$ echo 'for(var t=o=>{var i=+o;return i+i};t(););' | terser -c toplevel
ERROR: Cannot read property '_walk' of null

Above were inline=3 failures into loop conditions.

Here's a variation involving inline=3 into a AST_For.step:

$ echo 'for(var t=o=>{var i=+o;return i+i};;t());' | terser -c toplevel
ERROR: Cannot read property '_walk' of null

And another variation with inline=3 into an AST_IterationStatement body:

$ echo 'for(var t=o=>{var i=+o;return i+i};;)t();' | terser -c toplevel
ERROR: Cannot read property '_walk' of null

I'm not aware of a failing case that does not involve a loop.

Although it would be easier to eliminate inline=3 into loop headers and bodies altogether, it would be nice to find a proper fix without losing some of the optimizations already in place.

@fabiosantoscode
Copy link
Collaborator

Fixed as of 3.10.7

@jrjohnson
Copy link

Thank you!

@cosminstefanxp
Copy link

This seems to have popped up again. I'm getting the following:

js/app.60dfa2ad.js from Terser
TypeError: Cannot read property 'minify' of undefined
    at minify (/Users/cosmin/dev/get-gdpr/frontend/node_modules/terser-webpack-plugin/dist/minify.js:175:23)
    at module.exports (/Users/cosmin/dev/get-gdpr/frontend/node_modules/terser-webpack-plugin/dist/worker.js:13:40)
    at handle (/Users/cosmin/dev/get-gdpr/frontend/node_modules/worker-farm/lib/child/index.js:44:8)
    at process.<anonymous> (/Users/cosmin/dev/get-gdpr/frontend/node_modules/worker-farm/lib/child/index.js:51:3)
    at process.emit (events.js:182:13)
    at emit (internal/child_process.js:812:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)

when using Terser 3.16.0 with terser-webpack-plugin 1.2.1, but seems to work fine when using 3.14.0.

@mukeshyadav
Copy link

getting same issue, using CRA2 "react": "^16.5.2",
"react-dom": "^16.5.2",
"react-scripts": "^2.0.5"

@saintsatplay2015
Copy link

saintsatplay2015 commented Feb 2, 2019

This is an issue when trying to build Ionic 4 production apps - receiving following error message:
ERROR in common.00974306b5124fe008c9.js from Terser TypeError: Cannot read property 'minify' of undefined at minify (/ionic-pwa/ionic-pwa/node_modules/terser-webpack-plugin/dist/minify.js:175:23) at module.exports (/ionic-pwa/node_modules/terser-webpack-plugin/dist/worker.js:13:40) at handle (/ionic-pwa/node_modules/worker-farm/lib/child/index.js:44:8) at process.<anonymous> (/ionic-pwa/node_modules/worker-farm/lib/child/index.js:51:3) at emitTwo (events.js:126:13) at process.emit (events.js:214:7) at emit (internal/child_process.js:772:12) at _combinedTickCallback (internal/process/next_tick.js:141:11) at process._tickCallback (internal/process/next_tick.js:180:9)

This happens when using using Terser 3.16.0 with terser-webpack-plugin 1.2.1.
Like the above report from @cosminstefanxp I also tried downgrading version of Terser to Terser 3.14.0 with terser-webpack-plugin 1.2.1 and this works.

@jrjohnson
Copy link

The best way to get started solving this is probably to open a new issue and follow the steps in the comments above to create a reduced test case.

@filipesilva
Copy link

filipesilva commented Feb 2, 2019

There is already an issue for Cannot read property 'minify' of undefined: #251

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants