Skip to content

Fix property access on an object literal #17919

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
merged 12 commits into from
Sep 21, 2017
Merged

Fix property access on an object literal #17919

merged 12 commits into from
Sep 21, 2017

Conversation

henrymercer
Copy link
Contributor

@henrymercer henrymercer commented Aug 19, 2017

Fixes #10129.

Currently a property access on an object literal e.g. { a : 1 } can compile to { a : 1 }.x, which is incorrect syntax. This fixes object literal property accesses to compile to ({ a : 1 }.x), and fixes existing tests that have been using this incorrect syntax.

@msftclas
Copy link

@henrymercer,
Thanks for your contribution.
To ensure that the project team has proper rights to use your work, please complete the Contribution License Agreement at https://cla.microsoft.com.

It will cover your contributions to all Microsoft-managed open source projects.
Thanks,
Microsoft Pull Request Bot

@msftclas
Copy link

@henrymercer, thanks for signing the contribution license agreement. We will now validate the agreement and then the pull request.

Thanks, Microsoft Pull Request Bot

@saschanaz
Copy link
Contributor

Why only empty object literal? (<any>{a:3}).toString() also causes the issue.

@henrymercer henrymercer changed the title Fix empty object literal property access Fix object literal property access Aug 28, 2017
@henrymercer henrymercer changed the title Fix object literal property access Fix property access on an object literal Sep 3, 2017
Copy link
Contributor

@mhegazy mhegazy left a comment

Choose a reason for hiding this comment

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

Most of the changes to the baselines should go away if you check if the parent is not an expression statement.

const emittedExpression = skipPartiallyEmittedExpressions(expression);
if (isLeftHandSideExpression(emittedExpression)
&& (emittedExpression.kind !== SyntaxKind.NewExpression || (<NewExpression>emittedExpression).arguments)) {
&& (!isNewExpression(emittedExpression) || (<NewExpression>emittedExpression).arguments)
&& !isObjectLiteralExpression(emittedExpression)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this is only true if this is an expression statement. i.e.

var x = {a: 1}.a;   // OK

{a: 1}.a;   // Error

Copy link
Contributor

@rbuckton rbuckton left a comment

Choose a reason for hiding this comment

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

This is an incorrect fix as it aggressively adds parenthesis around object literals in positions where a property access was previously legal.

The issue only occurs when the object literal is the left-most expression in an expression statement. For the most part, we already handle this case in parenthesizeExpressionForExpressionStatement:

// ts
(<any>{}).x;

// js
({}.x);

However, It does look like there is a bug in parenthesizeExpressionForExpressionStatement when the outermost expression is a call.

You can see an example of the issue here: http://www.typescriptlang.org/play/index.html#src=%2F%2F%20ok%0D%0A(%3Cany%3E%7B%7D).x%3B%0D%0A%2F%2F%20error%0D%0A(%3Cany%3E%7B%7D).x()%3B%0D%0A

The easiest fix is to just lift the else block in factory.ts, line 3944 so that it performs the check for leftmost expression unconditionally.

@@ -37,13 +37,13 @@ x = [true][0];
x; // boolean
_a = [1][0], x = _a === void 0 ? "" : _a;
x; // string | number
(x = { x: true }.x);
(x = ({ x: true }).x);
Copy link
Contributor

Choose a reason for hiding this comment

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

The parenthesis aren't needed here.

Modify parenthesizeExpressionForExpressionStatement to add brackets around an expression statement in which the left-most expression is an object literal.
@henrymercer
Copy link
Contributor Author

Thanks @rbuckton, adding the parentheses around the whole property access expression in parenthesizeExpressionForExpressionStatement also fixes the problem and is much less aggressive in doing so. I have implemented the fix as you suggested.

@rbuckton rbuckton merged commit d9951cb into microsoft:master Sep 21, 2017
@rbuckton
Copy link
Contributor

Thanks for the contribution!

@henrymercer henrymercer deleted the fix-empty-object-property-access branch October 16, 2017 18:58
@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Object literal cast compiles to produce JS with syntax error
5 participants