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

Fix: AST_Accessor missing start / end tokens #1493

Closed
wants to merge 7 commits into from
Closed

Fix: AST_Accessor missing start / end tokens #1493

wants to merge 7 commits into from

Conversation

OndrejSpanel
Copy link
Contributor

Fix for #1492

@alexlamsl
Copy link
Collaborator

Any test to show what issue it caused and whether this fix is working as intended?

@OndrejSpanel
Copy link
Contributor Author

I will prepare the test. What location should I use for the test - a new file in test/mocha?

@alexlamsl
Copy link
Collaborator

test/mocha sounds good - there are a couple of other files with tests related to UglifyJS.parse() already.


// test there are no nodes without tokens
var checkWalker = new UglifyJS.TreeWalker(function(node, descend) {
assert(node.start !== undefined);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, can we be more precise about the value of start and end here?

Preferably with the source code under test spans multiple lines so we can reasonably sure the fields have been populated with sensible values?

lib/parse.js Outdated
@@ -1320,11 +1320,17 @@ function parse($TEXT, options) {
var type = start.type;
var name = as_property_name();
if (type == "name" && !is("punc", ":")) {
var createAccessor = function() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks somewhat similar to embed_tokens() which is use extensively throughout this file. Would you mind considering whether we can reuse that in this case as well?

Copy link
Contributor Author

@OndrejSpanel OndrejSpanel Feb 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not mind, however this is beyond my current JS abilities. What I have tried is:

                a.push(new AST_ObjectGetter({
                    start : start,
                    key   : as_atom_node(),
                    value : embed_tokens(function(){function_(AST_Accessor)}),
                    end   : prev()
                }));

This resulted in a parse error. If you can advise me how do to his properly, I will be glad to implement it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm typing from mobile, but this might work:

var createAccessor = embed_tokens(function() {
  return function_(AST_Accessor);
});

If not, I'll be back in a couple of hours and will take a look then.

Copy link
Contributor Author

@OndrejSpanel OndrejSpanel Feb 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried that (and thought: "Silly me. off course I have to return in JS, this is not Scala "), but I still get the parsing error:

'SyntaxError: Unexpected token punc «(», expected punc «,»'

My code was:

            var createAccessor = function() {embed_tokens(function() {
                return function_(AST_Accessor);
            })};

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused - did you try my suggestion or yours? Yours has an extra function() {...} wrapped around it.

Copy link
Contributor Author

@OndrejSpanel OndrejSpanel Feb 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried both, first what you wrote, then this - I was afraid your solution executes outside of the get / set scopes, now I see it does not - it returns a function, and executes nothing on its own.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarifying. I'll have a closer look when I get home.

Copy link
Contributor Author

@OndrejSpanel OndrejSpanel Feb 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tried your solution once again and I see its error is different. It outputs no parsing error, only the test is not passed, with assertion:

AssertionError: 22 == 12

What is the correct result - In the test code var obj = { get latest() { return undefined; } }, where should the accessor node start? Pos. 22 is right behind latest, pos. 12 is the beginning of get.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking http://lisperator.net/uglifyjs/ast, I think 22 makes more sense as a result, AST_Accessor is a child of AST_Lambda, and has no name. I am committing your implementation and adjusting the test,

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OndrejSpanel thanks for the detailed investigation 👍

var checkWalker = new UglifyJS.TreeWalker(function(node, descend) {
if (node instanceof UglifyJS.AST_Accessor) {
assert.equal(node.start.pos, 22);
assert.equal(node.end.endpos, 46);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't the AST_Accessor start at 12 - the beginning of the get keyword?

get latest() { return undefined; }

Copy link
Contributor Author

@OndrejSpanel OndrejSpanel Feb 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think is is a matter of opinion. I will try to explain why I think with it should start at 22:

The AST hierarchy is:
AST_ObjectProperty contains

  • key of type AST_KeySymbolRef
  • value of type AST_Accessor

As key is what contains the property name, I think it makes a sense to let the AST_Accessor to start after it. Perhaps its name is a bit misleading and it should be called something like AST_AccessorBody, but I doubt you will want to break AST compatibility because of this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. For what it's worth, acorn reports the FunctionExpression start at 22 as well.

What is the start/end for the AST_ObjectProperty for get latest() { return undefined; }?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The start/end for the AST_ObjectProperty is 12 / 46.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please check the AST_ObjectProperty start/end, as well as the AST_KeySymbolRef start/end in the test as well?

@OndrejSpanel
Copy link
Contributor Author

The build has failed because of timeout in completely unrelated code. I doubt it is related to my fix, but I do not know.

@alexlamsl
Copy link
Collaborator

@OndrejSpanel the build failed due to a spurious time-out, the fix of which is available but pending to be merged.

You can restart the CI test by re-opening this PR.

assert.equal(node.end.endpos, 46);

assert(node.key instanceof UglifyJS.AST_SymbolRef);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could not use the same way as before, as Walker is not visiting the key node, therefore it needs to be accessed from its parent. I like it more this way anyway.

Copy link
Contributor

@kzc kzc Feb 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically you don't need a tree walker at all. You could access each node from the toplevel ast node directly.

@OndrejSpanel
Copy link
Contributor Author

I think I have implemented all changes you required. Is there anything else?

@alexlamsl
Copy link
Collaborator

alexlamsl commented Feb 20, 2017

@OndrejSpanel IMHO two nits would be the naming (create_accessor) and moving it out of scope so it doesn't get recreated for every iteration of while within every invocation of object_

Otherwise it looks functionally correct. If another reviewer approves, I'll lump this on top of #1485.

Edit: also I think this project prefers the commits to be squashed into one. But I can do that if it proves to be too much hassle.

alexlamsl pushed a commit to alexlamsl/UglifyJS that referenced this pull request Feb 20, 2017
@alexlamsl
Copy link
Collaborator

@OndrejSpanel pushed to #1485 as 89e94b2 - thanks!

@alexlamsl alexlamsl closed this in d48a308 Feb 23, 2017
@alexlamsl alexlamsl mentioned this pull request Feb 27, 2017
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 this pull request may close these issues.

3 participants