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

Question about comments deletion #578

Closed
edoardocavazza opened this issue Dec 5, 2020 · 5 comments
Closed

Question about comments deletion #578

edoardocavazza opened this issue Dec 5, 2020 · 5 comments

Comments

@edoardocavazza
Copy link

Hello!

Why does esbuild strips out comments even when minification is not required? Having an option to leave comments could be useful for interoperability. For example, istanbul refers to some comments to ignore part of the code when computing the coverage.

@evanw
Copy link
Owner

evanw commented Dec 5, 2020

This is a duplicate of #516. Here is my reply from that thread:

You are correct, esbuild does not preserve comments. It's not built to preserve comments. Preserving comments means it would operate more like a code formatter than a compiler. For example, you would probably want a token spanning tree instead of an AST. Doing this is currently a non-goal of esbuild. You should probably be using another tool for this.

@edoardocavazza
Copy link
Author

Thank you @evanw for your reply, I am sorry but somehow I did not manage to found the old issue. I am not sure to have got the point, but I thought that since esbuild preserves @license comments would be able to handle other comment types. Does it apply to/*#__PURE__*/ annotations too? I was just wondering if those comments should be in the scope of a bundler, since their offer informations about side effects.

@evanw
Copy link
Owner

evanw commented Dec 7, 2020

Comment preservation is generally done with specific semantics in mind since the comments are usually annotations that mean something specific.

Semantically /*#__PURE__*/ comments apply to the following call or new expression. This means they are essentially parsed as a unary prefix operator with a high operator precedence. They should be attached to that call or new expression and should be removed, reordered, or duplicated as such.

Semantically @license comments apply to the file they are in. Since they are usually at the top or bottom of the file, currently only @license comments in statement position are preserved by esbuild. These comments are independent of any other statements in the file and may be reordered if the surrounding AST nodes move around or are removed. Also unlike all other comments, these comments are supposed to be preserved during minification. And during minification these comments are extracted from their respective files, deduplicated to save space, and collected at the end of the bundle instead. This is because semantically repeated identical @license comments still have the same meaning as a single copy and using a single copy saves space.

Comments for Istanbul have different semantics that are specific to Istanbul. I'm not familiar with Istanbul but from what I've read here it's something like this:

  1. Coverage can be explicitly skipped using comments. There is no automatic pattern match of expressions to determine if they should be skipped for coverage.
  2. A coverage skip hint looks like /* istanbul ignore <word>[non-word] [optional-docs] */
  3. For if conditions you can say /* istanbul ignore if */ or /* istanbul ignore else */ and that will end up ignoring whichever path was required to be ignored.
  4. For all other cases, the Swiss army knife /* istanbul ignore next */ may be used which skips the "next thing" in the source code
  5. The "next" thing may be, among other things:
    • A JS statement (including assignments, ifs, loops, switches, functions) in which case all of the statement is ignored for all forms of coverage.
    • A switch case statement, in which case the particular case is ignored for branch coverage and its contents ignored for all forms
    • A conditional inside a ternary expression in which case the branch is ignored
    • A part of a logical expression in which case that part of the expression is ignored for branch coverage
  6. It is up to the caller to scope this as narrowly as possible. For example, if you have a source file that is wrapped in a function expression, adding /* istanbul ignore next */ at the top of the file will ignore the whole file!

To pass these comments through esbuild's build pipline correctly (including tree shaking, constant folding, code reordering, dead code elimination, etc.) esbuild would have to encode comments using Istanbul's specific notion of "next thing" in its AST.

Other tools requiring comment preservation for their own purposes may have different needs altogether. For example, I could imagine that some other tools use line-by-line comments and would require that esbuild preserve the line breaks in between operators and/or the number of lines in between comments.

I want esbuild to be a general-purpose tool without having to encode the specifics of many other tools into esbuild itself. So I believe this to be out of esbuild's scope. The general way of solving all of these use cases is to use something more like a code formatter that preserves the original source code as much as possible.

Other tools are better set up to do this. I believe Rollup does something like this with the magic string library, for example. This is not easy to do for esbuild because internally it's built more like a compiler instead of a code formatter.

@edoardocavazza
Copy link
Author

Thanks for the explanation, I am going to close this issue 🙂

@hans-bala-glean
Copy link

Anyone coming by here, you can use https://esbuild.github.io/api/#legal-comments

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

No branches or pull requests

3 participants