-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Fix property access on an object literal #17919
Conversation
@henrymercer, It will cover your contributions to all Microsoft-managed open source projects. |
@henrymercer, thanks for signing the contribution license agreement. We will now validate the agreement and then the pull request. |
Why only empty object literal? |
There was a problem hiding this 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.
src/compiler/factory.ts
Outdated
const emittedExpression = skipPartiallyEmittedExpressions(expression); | ||
if (isLeftHandSideExpression(emittedExpression) | ||
&& (emittedExpression.kind !== SyntaxKind.NewExpression || (<NewExpression>emittedExpression).arguments)) { | ||
&& (!isNewExpression(emittedExpression) || (<NewExpression>emittedExpression).arguments) | ||
&& !isObjectLiteralExpression(emittedExpression)) { |
There was a problem hiding this comment.
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
There was a problem hiding this 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); |
There was a problem hiding this comment.
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.
Thanks @rbuckton, adding the parentheses around the whole property access expression in |
Thanks for the contribution! |
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.