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

Invalid left-hand side in for-in #1944

Open
yuanzm opened this Issue Jul 11, 2018 · 3 comments

Comments

Projects
None yet
4 participants
@yuanzm

yuanzm commented Jul 11, 2018

Steps to reproduce

// some code from TweenMax.min.js
var code = `
function a() {
				var e, i, n, a, o = this._tween,
					l = o.vars.roundProps,
					h = {},
					_ = o._propLookup.roundProps;
				if ("object" != (void 0 === l ? "undefined" : t(l)) || l.push) for ("string" == typeof l && (l = l.split(",")), n = l.length; --n > -1;) h[l[n]] = Math.round;
				else for (a in l) h[a] = s(l[a]);
				for (a in h) for (e = o._firstPT; e;) i = e._next, e.pg ? e.t._mod(h) : e.n === a && (2 === e.f && e.t ? r(e.t._firstPT, h[a]) : (this._add(e.t, a, e.s, e.c, h[a]), i && (i._prev = e._prev), e._prev ? e._prev._next = i : o._firstPT === e && (o._firstPT = i), e._next = e._prev = null, o._propLookup[a] = _)), e = i;
				return !1
			}
`
esprima.parse(code);

Expected output

AST tree

Actual output

Error: Line 8: Invalid left-hand side in for-in
at ErrorHandler.constructError (/Users/yuanzimin/tmp/minigame-code-check/node_modules/esprima/dist/esprima.js:5004:22)
at ErrorHandler.createError (/Users/yuanzimin/tmp/minigame-code-check/node_modules/esprima/dist/esprima.js:5020:27)
at ErrorHandler.tolerateError (/Users/yuanzimin/tmp/minigame-code-check/node_modules/esprima/dist/esprima.js:5030:27)
at Parser.tolerateError (/Users/yuanzimin/tmp/minigame-code-check/node_modules/esprima/dist/esprima.js:1951:28)
at Parser.parseForStatement (/Users/yuanzimin/tmp/minigame-code-check/node_modules/esprima/dist/esprima.js:3802:31)
at Parser.parseStatement (/Users/yuanzimin/tmp/minigame-code-check/node_modules/esprima/dist/esprima.js:4127:43)
at Parser.parseIfClause (/Users/yuanzimin/tmp/minigame-code-check/node_modules/esprima/dist/esprima.js:3647:22)
at Parser.parseIfStatement (/Users/yuanzimin/tmp/minigame-code-check/node_modules/esprima/dist/esprima.js:3665:35)
at Parser.parseStatement (/Users/yuanzimin/tmp/minigame-code-check/node_modules/esprima/dist/esprima.js:4133:43)
at Parser.parseStatementListItem (/Users/yuanzimin/tmp/minigame-code-check/node_modules/esprima/dist/esprima.js:3378:39)

If I replace the code in line 8

else for (a in l) h[a] = s(l[a]);

with

else { for (a in l) h[a] = s(l[a]); }

or

else for (var a in l) h[a] = s(l[a]);

It works!!
I tried to read the source code,but it was too complicated.... help...

@ariya

This comment has been minimized.

Contributor

ariya commented Jul 16, 2018

I can reproduce it. Looks like a terrible bug, I have a look. Thanks for the detailed report!

@ariya ariya added the defect label Jul 16, 2018

@lmy375

This comment has been minimized.

lmy375 commented Aug 15, 2018

I met same issue recently. Here is a simpler PoC script.

if (1)
    for (a of '1'){} // after parsing '1', context.isAssignmentTarget is set false.
else
    for (v in v){}  // while parseing this statement, context.isAssignmentTarget is set still false.

With some debugging I think the root cause is probably that isAssignmentTarget flag is not reset each time before starting parsing a new statement.

    parseStatement(): Node.Statement {
+       this.context.isAssignmentTarget = true;
        let statement: Node.Statement;
        switch (this.lookahead.type) {
            case Token.BooleanLiteral:

After patching this, esprima works on PoC script! But I'm not sure if this will lead to other side effects.

@betalb

This comment has been minimized.

betalb commented Oct 31, 2018

Putting brackets around else block, also hides issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment