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(babel-parser): delete static property from class static block for TS #13680

Merged
merged 6 commits into from Aug 25, 2021

Conversation

sosukesuzuki
Copy link
Member

@sosukesuzuki sosukesuzuki commented Aug 15, 2021

Q                       A
Fixed Issues? Fixes #13674
Patch: Bug Fix? Y
Tests Added + Pass? Yes
License MIT

context: I noticed the bug when implementing to support static blocks for typescript-estree (ref :https://github.com/typescript-eslint/typescript-eslint/pull/3730/files#diff-f3405000b53c5abe00cbd3f4852b524d0e84478a76b8f8da33eecfe9acfc97f4R253-R256)

@sosukesuzuki sosukesuzuki added PR: Bug Fix 🐛 A type of pull request used for our changelog categories pkg: parser area: typescript labels Aug 15, 2021
@babel-bot
Copy link
Collaborator

babel-bot commented Aug 15, 2021

Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/48314/

@codesandbox-ci
Copy link

codesandbox-ci bot commented Aug 15, 2021

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 828b241:

Sandbox Source
babel-repl-custom-plugin Configuration
babel-plugin-multi-config Configuration

@@ -2396,6 +2396,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
const callParseClassMemberWithIsStatic = () => {
const isStatic = !!member.static;
if (isStatic && this.eat(tt.braceL)) {
delete member.static;
Copy link
Contributor

Choose a reason for hiding this comment

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

Deleting a property should be generally avoided (https://stackoverflow.com/a/44008788/1490357), especially when it is executed for normal execution path: static blocks. I think we can check if a tt.braceL is upcoming before member.static is assigned in tsParseModifiers.

Copy link
Member Author

Choose a reason for hiding this comment

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

It was difficult to avoid to attach static in tsParseModifiers without failing existing tests. So what do you think about to separate attaching modifier properties and parsing ( d5077ff )?

} else if (modifier !== "static") {
member[modifier] = true;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Object clone is also slow. Can we check tt.braceL when modifier === "static" in

?

For cases like static declare { }, it doesn't matter if static is set because static block can not have any modifiers.

Copy link
Member Author

Choose a reason for hiding this comment

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

We can check it in parseModifiers. But if we do that, we cannot know from the parseClassMember whether a member is static or not in

const isStatic = !!member.static;
if (isStatic && this.eat(tt.braceL)) {

Copy link
Member Author

Choose a reason for hiding this comment

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

It breaks some invalid test cases( static block has modifier ), but able to avoid deleting properties and copying objects by lookahead ( lookaheadCharCode ) them. What do you think? (f09c7f6, 57824b9)

Copy link
Contributor

Choose a reason for hiding this comment

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

In that case we can have parseModifiers stopped at static { so we can still recover from cases when modifiers are on static block.

See also https://github.com/microsoft/TypeScript/blob/7a19c22063660da0b2f03fca97178679814de1e7/src/compiler/parser.ts#L6916-L6919

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for telling it me. I've fixed by referring to the TypeScript parser code ( d743bc8 )

@sosukesuzuki sosukesuzuki force-pushed the fix-13674 branch 2 times, most recently from 57824b9 to d743bc8 Compare August 18, 2021 22:42
@@ -1,9 +1,6 @@
{
"type": "File",
"start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"errors": [
"SyntaxError: Duplicate modifier: 'static'. (2:9)"
],
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 a regression, the input is

class Foo {
  static static {}
}

Copy link
Member Author

Choose a reason for hiding this comment

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

@JLHwung Can you review again?

@@ -1,3 +1,3 @@
class Foo {
static public {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Q: Do we already have test cases covering static public?

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

That one is a static public class method. I mean static public {}, which should throw. Just wondering why the test case is changed, we can always add new test cases for public static {}.

Copy link
Member

Choose a reason for hiding this comment

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

Oops sorry, I misread the changed one🤦‍♂️

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, I've added more tests (5ea75b9, 828b241). However, the syntax static followed by modifier followed by block({ }) is not recoverable. (TypeScript Compiler also doesn't seem to be able to throw a friendly error for such code (TypeScript Playground link))

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah we can always improve it later as long as we don't pass invalid input.

@@ -1,3 +1,3 @@
class Foo {
static public {}
Copy link
Member

Choose a reason for hiding this comment

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

@JLHwung JLHwung merged commit b141c85 into babel:main Aug 25, 2021
@sosukesuzuki sosukesuzuki deleted the fix-13674 branch August 26, 2021 03:09
@github-actions github-actions bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label Nov 25, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 25, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: typescript outdated A closed issue/PR that is archived due to age. Recommended to make a new issue pkg: parser PR: Bug Fix 🐛 A type of pull request used for our changelog categories
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug]: Invalid static property for StaticBlock
5 participants