Skip to content

[CS2] Fix #4467: tagged template literal call #4601

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

Merged

Conversation

helixbass
Copy link
Collaborator

Fixes #4467

I came to this issue from the other direction - I'd noticed in the grammar that Invocation (ie a function call) really ought to be a grammar Value - it simplifies things grammar-wise and makes intuitive sense. The one thing that I saw that that made legal (ie where previously you could use a Value but not an Invocation) was an Invocation as the "function" of a TaggedTemplateLiteral - so #4467 having been opened about that specific case validates my thinking

By making Invocation a grammar Value, its Call gets wrapped in a new Value() in places where it previously would've been an unwrapped Call (eg a().b). So mostly then had to go through and add some .unwrap()s in nodes.coffee where things were expecting an unwrapped Call but could now be getting a Call wrapped in a Value. There could be other places in nodes.coffee that should be updated in this way, I mostly just went through and found the places that were breaking tests

One interesting test breakage was the test in test/parser.coffee that checks the locationData of a = new B().c(d). This led me through #619 which explains that the AST for new expressions like this aren't actually correct (ie don't match JS' interpretation, just generate the correct compiled JS). But the actual bug ended up being that the location data for Values with properties don't include the properties. The test was previously passing because in the grammar rule o 'Invocation Accessor', -> new Value $1, [].concat $2, the new Value() is initialized with its property. But with the grammar change, the property was being .add()ed to the Value later. So this basically just exposed the bug that typical Values with properties don't include the properties' locations in their location data. From my understanding this is because once locationData is set (at the time the grammar rule creating the new Value() is run), updateLocationDataIfMissing() will then ignore the subsequent (correct, expanded) location data that gets sent when the rule o 'Value Accessor', -> $1.add $2 gets run. So I added a workaround for this specific case of .add()ing properties to Values

There are a couple other little nodes.coffee cleanups included, I'll make some comments on the code @GeoffreyBooth

o 'This'
o 'Super'
o 'Super', -> new Value $1
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this is the same grammar change from #4592 (to allow eg super.x.y), all the rest of the changes here in grammar.coffee are related to making Invocation a grammar Value

@@ -266,7 +266,8 @@ exports.Base = class Base
# For this node and all descendents, set the location data to `locationData`
# if the location data is not already set.
updateLocationDataIfMissing: (locationData) ->
return this if @locationData
return this if @locationData and not @forceUpdateLocation
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this @forceUpdateLocation is the workaround I described in the PR comment - it gets set inside Value.add() below to allow the subsequent call to updateLocationDataIfMissing() with (seemingly correct) updated location data that includes the location of the added property to flow through and set the Value's locationData. This was the cleanest way I could see to allow updating the locationData for this one case

@@ -2635,7 +2637,8 @@ exports.Op = class Op extends Base
if op is 'do'
return Op::generateDo first
if op is 'new'
return first.newInstance() if first instanceof Call and not first.do and not first.isNew
if (firstCall = first.unwrap()) instanceof Call and not firstCall.do and not firstCall.isNew
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this and the two other below changes to nodes.coffee are places where a Call that's now wrapped in a Value (due to the grammar changes) needed to be unwrapped in order for tests to pass


test 'Values with properties end up with a location that includes the properties', ->
source = '''
a.b
Copy link
Collaborator

Choose a reason for hiding this comment

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

In addition to this test, perhaps another that has a bit more code around it? Perhaps with new? So that we have more confidence that the location data is correct.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@GeoffreyBooth I'd say the new case is already covered by the new calls have a range including the new test in test/parser.coffee that led me to this bug, but I added more cases here that test multiple accesses/indexes

@GeoffreyBooth GeoffreyBooth added this to the 2.0.0 milestone Jul 4, 2017
@GeoffreyBooth
Copy link
Collaborator

LGTM. @lydell?

@lydell
Copy link
Collaborator

lydell commented Jul 5, 2017

LGTM

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