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

Annotating transformed classes with #__PURE__ comment #6209

Merged
merged 1 commit into from Sep 11, 2017

Conversation

Andarist
Copy link
Member

@Andarist Andarist commented Sep 7, 2017

Q                       A
Fixed Issues fixes #5632
Patch: Bug Fix? no
Major: Breaking Change? no
Minor: New Feature? yes
Tests Added/Pass? yes
Spec Compliancy?
License MIT
Doc PR no
Any Dependency Changes? no

This is a simple change which annotate created by transform-es2015-classes IIFEs with #__PURE__ comments. This allows UglifyJS to remove those IIFE calls if their result is unused - generally speaking it allows for better Dead Code Elimination.

The core of the change is here. The rest are only adjusted tests.

@babel-bot
Copy link
Collaborator

babel-bot commented Sep 7, 2017

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

@nicolo-ribaudo
Copy link
Member

Does UglifyJS remove this?

var A = /*#__PURE__*/ /* foo */ function() { /* ... */ }(X);

Which is the output for

var A = /* foo */ class A extends X {}

@nicolo-ribaudo
Copy link
Member

Also, maybe this should be enabled using an option since not everyone uses UglifyJS after Babel?

@Andarist
Copy link
Member Author

Andarist commented Sep 7, 2017

Does UglifyJS remove this?
var A = /#PURE/ /* foo / function() { / ... */ }(X);

Unfortunately not. They explicitly check only the last comment. I might poke around in the UglifyJS repo as well to make this work, or at least investigate why it doesnt.

Which is the output for
var A = /* foo */ class A extends X {}

Should be easy to add #__PURE__ as the last leading comment instead of putting it as first one. Ofc some other plugin could mess this up again. So the true solution is to work this out in UglifyJS itself. However this is quite an edge case (I dont believe many people use comments like this, also not that many plugins annotating functions like this) and I believe this could stay unchanged.

Also, maybe this should be enabled using an option since not everyone uses UglifyJS after Babel?

Ive also thought about this, however:

  • I believe its better to have opt-out option. The biggest concern for me is that most people are not fully aware of the tools they use and how they work and I believe its better to add such comments by default and provide an option to disable this if somebody doesnt want it. Usage of UglifyJS is so vast in the community that it sounds reasonable to me to emit those annotations by default.
  • I hadnt time to investigate how passing through options from the presets to the plugins should be done ;)

@hzoo
Copy link
Member

hzoo commented Sep 9, 2017

It's fine as a default since it's a comment anyway, I was just confused as to what the comment is supposed to be? I thought it was @class before too @kzc

Copy link
Member

@hzoo hzoo left a comment

Choose a reason for hiding this comment

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

good, pending review by @kzc or someone on uglify

also cc @boopathi

var Foo = function (_Bar) {
var Foo =
/*#__PURE__*/
function (_Bar) {
Copy link

Choose a reason for hiding this comment

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

This is not important... but is there a reason why this is on 3 lines instead of 1?

Copy link
Member Author

Choose a reason for hiding this comment

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

its just how babel-generator spits out code from the AST, looks weird to me too, but 🙄

Copy link
Member

Choose a reason for hiding this comment

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

It's probably just because we removed some logic with newlines using tokens/comments so it's like that now

@kzc
Copy link

kzc commented Sep 9, 2017

Seems fine. I assume @Andarist verified the result against uglify.

Will non-standard static class properties be generated within the IIFE as per #5632 (comment)?

Copy link
Member

@xtuc xtuc left a comment

Choose a reason for hiding this comment

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

Lgtm 👍

@@ -2,6 +2,8 @@ import LooseTransformer from "./loose";
import VanillaTransformer from "./vanilla";
import nameFunction from "babel-helper-function-name";

const PURE_ANNOTATION = "#__PURE__";
Copy link
Member

Choose a reason for hiding this comment

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

We could use this across multiple plugins? We might want to add it in a helper.

Copy link
Member Author

Choose a reason for hiding this comment

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

@xtuc sure thing, whats the best place to add such?

Copy link
Member

Choose a reason for hiding this comment

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

Too late but I had something like babel-help-emit-pure-annotation in mind but I'm not sure it will be used apart from here.

Copy link
Member

Choose a reason for hiding this comment

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

I would just make it when we need/get to it. It's not a breaking change to swap it out either

@Andarist
Copy link
Member Author

Andarist commented Sep 9, 2017

Will non-standard static class properties be generated within the IIFE as per #5632 (comment)?

I plan to work on it too, need to establish how it should be done though. The problem I see is that those 2 plugins are independent but they need to work together here somehow. Ideally also we could have 2 different outputs for:

  • transpiled classes - just pull statics into the closure
  • only transpiled statics - wrap class + statics into the closure

@Andarist
Copy link
Member Author

Andarist commented Sep 9, 2017

It's fine as a default since it's a comment anyway, I was just confused as to what the comment is supposed to be? I thought it was @class before too @kzc

It seems that @class is emitted by the TS compiler and they refuse to use the #__PURE__ comment which is understandable by the UglifyJS - they propose that people use replacement plugins from @class to #__PURE__ comments i.e. with webpack plugin.

@kzc
Copy link

kzc commented Sep 9, 2017

Will non-standard static class properties be generated within the IIFE as per #5632 (comment) ?

The problem I see is that those 2 plugins are independent but they need to work together here somehow.

I ran into the same issue when hacking together the proof of concept. I did not know how Babel plugins are supposed to communicate/coordinate with each other - via Babylon AST only?

Maybe just eliminate babel-plugin-transform-class-properties altogether and roll that functionality into some future version of babel-plugin-transform-es201X-classes?

@carrickjason
Copy link

Will non-standard static class properties be generated within the IIFE as per #5632 (comment)?

I plan to work on it too, need to establish how it should be done though. The problem I see is that those 2 plugins are independent but they need to work together here somehow. Ideally also we could have 2 different outputs for:

  • transpiled classes - just pull statics into the closure
  • only transpiled statics - wrap class + statics into the closure

@Andarist Do you know if this got solved anywhere? I'm still seeing class properties outside of the IIFE which is breaking treeshaking.

@Andarist
Copy link
Member Author

You could try this https://github.com/emotion-js/emotion/blob/64a39f1eb6abf5afe6949b702436423938f34fd0/scripts/build/fix-dce-for-classes-with-statics.js , just keep in mind that this might break your code - it's not overly tested 😉

I unfortunately couldn't find time yet to revive my old PR to fix this issue, I was hoping that this PR would get merged in #8130 which would the whole WAY easier.

@lock lock bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label Oct 4, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Oct 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated A closed issue/PR that is archived due to age. Recommended to make a new issue PR: New Feature 🚀 A type of pull request used for our changelog categories
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Pure annotation in downlevel emits
8 participants