Skip to content

Have rollup emit `let $safeClassName = class $originalClassName { ...… - #2025

Merged
lukastaegert merged 3 commits into
rollup:masterfrom
NaridaL:class-name-not-changed
Mar 7, 2018
Merged

Have rollup emit `let $safeClassName = class $originalClassName { ...…#2025
lukastaegert merged 3 commits into
rollup:masterfrom
NaridaL:class-name-not-changed

Conversation

@NaridaL

@NaridaL NaridaL commented Mar 2, 2018

Copy link
Copy Markdown
Contributor

…` instead of

class $safeClassName { ..., which changes the runtime behavior when MyClass.name
is accessed.

Added corresponding test.

if (this.id) {
const name = this.id.variable.getName()
if (name !== this.id.variable.name) {
code.appendRight(this.start, `let ${this.id.variable.safeName} = `)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not sure appendRight is the correct one. prependLeft doesn't work, in any case.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, appendRight is actually the right one. The name may feel a little counter-intuitive but it means

  • insert at the current position (just like appendLeft, prependRight and prependLeft)
  • if anything else was inserted at this position earlier, put this insertion last (this is the append part and certainly the right choice as we would not want anything to slip in between this insertion and the class)
  • if the code to the right is removed later for some other reason, remove this insertion as well (this is the right part and the reason why left would definitely be wrong here). So right means "attach this to the subsequent code" while left means "attach this to the preceding code"

@NaridaL

NaridaL commented Mar 2, 2018

Copy link
Copy Markdown
Contributor Author

Fixes the class part of #1914

@guybedford

Copy link
Copy Markdown
Contributor

Nice thanks for the PR! It seems like this is missing the test expectations from the commit?

@NaridaL

NaridaL commented Mar 2, 2018

Copy link
Copy Markdown
Contributor Author

As far as I could tell, the test/function tests are only checked by running the generated bundle? Where would expected baselines go?

@guybedford

Copy link
Copy Markdown
Contributor

Ah I misread this as a form test not a function one.

@guybedford guybedford left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Seems good to me. I'd be happier seeing output tests to ensure this works with all the formats, but thinking through the cases it seems like it will.

@NaridaL
NaridaL force-pushed the class-name-not-changed branch from 2dc6c7d to 2c64d83 Compare March 2, 2018 22:33
@NaridaL

NaridaL commented Mar 2, 2018

Copy link
Copy Markdown
Contributor Author

@guybedford Added a form test.


let MyClass$1 = class MyClass {
constructor() { }
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actually I think this is incorrect if we don't have automatic semicolon insertion here.

For example:

class Q {
} p();

is valid JavaScript, while:

let Q$1 = class Q {
} p()

is not!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch. Should I just unconditionally add a semicolon (or maybe a new line)? From what I could tell, it's not possible to check whether the next token is preceded by a new line without doing additional parsing manually.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

See https://github.com/rollup/rollup/blob/master/src/ast/nodes/ExportDefaultDeclaration.ts#L112 for a rough example of how this can work. I think the crux is just:

if (code.original[this.end] !== ';') {
  code.prependRight(this.end, ';');
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah, thanks for the example.

@NaridaL

NaridaL commented Mar 4, 2018

Copy link
Copy Markdown
Contributor Author

@guybedford I changed it to always add a semicolon: class declarations don't require semicolons, so if you have class X {};, the ; is parsed as a separate empty statement, which rollup removes, leaving no semicolons at all.

It might be worth checking if that's also an issue in the example you linked...

@guybedford guybedford left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good, boundary handling sounds fine from what you say. Thanks for the quick follow-up!

@lukastaegert lukastaegert left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just a slight change with the use of left vs right, otherwise this is good to go!

if (this.id) {
const name = this.id.variable.getName()
if (name !== this.id.variable.name) {
code.appendRight(this.start, `let ${this.id.variable.safeName} = `)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, appendRight is actually the right one. The name may feel a little counter-intuitive but it means

  • insert at the current position (just like appendLeft, prependRight and prependLeft)
  • if anything else was inserted at this position earlier, put this insertion last (this is the append part and certainly the right choice as we would not want anything to slip in between this insertion and the class)
  • if the code to the right is removed later for some other reason, remove this insertion as well (this is the right part and the reason why left would definitely be wrong here). So right means "attach this to the subsequent code" while left means "attach this to the preceding code"

Comment thread src/ast/nodes/ClassDeclaration.ts Outdated
const name = this.id.variable.getName()
if (name !== this.id.variable.name) {
code.appendRight(this.start, `let ${this.id.variable.safeName} = `)
code.prependRight(this.end, ';');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This, on the other hand, needs to be prependLeft with the explanation given above.

@lukastaegert lukastaegert added this to the 0.56.5 milestone Mar 6, 2018
NaridaL added 3 commits March 6, 2018 11:33
…` instead of

`class $safeClassName { ...`, which changes the runtime behavior when MyClass.name
is accessed.

Added corresponding tests.
@NaridaL
NaridaL force-pushed the class-name-not-changed branch from 8685092 to 785fdfc Compare March 6, 2018 10:37
@NaridaL

NaridaL commented Mar 6, 2018

Copy link
Copy Markdown
Contributor Author

@lukastaegert done, and I rebased it.

@lukastaegert lukastaegert left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, looks good!

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