Skip to content

Some comments are removed without options.output.comments judgement #575

Open

Description

@LongTengDao

Bug report or Feature request? Feature request

Version (complete output of terser -V or specific git commit) 4.6.3

Complete CLI command or minify() options used

options = {
	output: {
		comments ({}, { value }) {
			console.log(value);
			return true;
		}
	}
};

terser input

/*! license */
define(function () {
	
	'use strict';
	
	var A = /A/;
	
	/*! license for B */
	
	var B = /B/;
	
	return [ A, B ];
	
});

terser output or error

! license 
/*! license */
define((function(){"use strict";return[/A/,/B/]}));

Expected result

! license 
! license for B 
/*! license */
define((function(){"use strict";
/*! license for B */
return[/A/,/B/]}));

Activity

  1. fabiosantoscode commented on Feb 24, 2020

    @fabiosantoscode
    Collaborator

    We really need a way to create immovable comments :/ I'll give more thought to this in the coming weeks. Right now I'm focused on performance improvements, which should come out later this week or next week.

  2. fabiosantoscode commented on Feb 29, 2020

    @fabiosantoscode
    Collaborator

    I've e-mailed the free software foundation to inquire about this topic. They might allow this to happen as long as we place all software licenses at the top of the file for example, which is a very simple solution that makes it easier for the user to see what licenses the code has.

  3. mdr1384 commented on Apr 8, 2020

    @mdr1384

    FYI any time you compress multiple files which start out with an IIFE using the bang method, e.g. !function(e){...}(...), and which have a header comment, all the header comments are discarded except for the first file.

    I note that if the IIFE uses the parens method, e.g. (function(e) {...})(...), then there is no problem, it is only with the bang method that it fails. Also if you compress the files individually there is no problem (since it is always the first file in this case.)

    For example, if you want to combine bluebird.js and vue.min.js:

    terser -c --comments  -- assets/bluebird.js assets/vue.min.js > out.min.js
    // The output only has the license comment for bluebird.js
    terser -c --comments  -- assets/vue.min.js assets/bluebird.js > out.min.js
    // The output only has the license comment for vue.min.js
    terser -c --comments  -- assets/bluebird.js assets/vue.js > out.min.js
    // Now the output has both comments because vue.js uses the parens IIFE method.
    

    This same problem happens with uglifyjs ver 3. It seems pretty serious to me since there doesn't seem to be any good workaround (except disabling compression) and I am typically combining dozens of various JS libraries and who knows what license statements are being left out (generally all but the first one.)

  4. fabiosantoscode commented on Apr 8, 2020

    @fabiosantoscode
    Collaborator

    That's interesting. I really think the way we handle comments needs an overhaul. It's extremely finicky, and things go wrong all the time.

    I wish we could move to a standard way of representing licenses, but the standard way of representing licenses involves a HTML page and this is not something Terser is in a position to push upon its users.

    edit: this is what the FSF suggested after I e-mailed them.

  5. LongTengDao commented on Apr 9, 2020

    @LongTengDao
    ContributorAuthor

    After read some open source license documents again carefully, I found that, whether we reserved the comments, we all didn't follow the license well, because they usually require to include the whole license file, which even authors of the original pack didn't do.

  6. fabiosantoscode commented on Apr 9, 2020

    @fabiosantoscode
    Collaborator

    If you compile binary code, you don't write the license onto the binary. Nobody is reading it! You need to specify licenses separately, in general you have a section of your app or option of your tool for OSS licenses, or distribute the license text next to the executable. Minified JS should be the same right? What the FSF suggests is just a standardised way of letting people and code know what licenses you use.

  7. mdr1384 commented on Apr 9, 2020

    @mdr1384

    FYI What I ended up doing:

    1. Quit using the --comment parameter
    2. Minify all the JS together: terser -c -m -- (list of 55 js files) > out.min.js
    3. Grab all the header comments (using the esprima parser) and concat to the output file: esheader (list of 55 js files) >> out.min.js

    So now the headers are all in there, just not attached to the original code, but now all at the end. My custom program puts the original filename in there too, so for my previous example using bluebird.js and vue.min.js, I now get:

    $ terser -c -m -- bluebird/bluebird.js vue/vue.min.js > out.min.js
    $ esheader bluebird/bluebird.js vue/vue.min.js >> out.min.js
    $ wc out.min.js
          34    3749  172028 out.min.js
    $ tail -33 out.min.js
    //! File: vue/vue.min.js
    /*!
     * Vue.js v2.6.11
     * (c) 2014-2019 Evan You
     * Released under the MIT License.
     */
    
    //! File: bluebird/bluebird.js
    /* @preserve
     * The MIT License (MIT)
     *
     * Copyright (c) 2013-2017 Petka Antonov
     *
     * Permission is hereby granted, free of charge, to any person obtaining a copy
     * of this software and associated documentation files (the "Software"), to deal
     * in the Software without restriction, including without limitation the rights
     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     * copies of the Software, and to permit persons to whom the Software is
     * furnished to do so, subject to the following conditions:
     *
     * The above copyright notice and this permission notice shall be included in
     * all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     * THE SOFTWARE.
     *
     */
    
  8. fabiosantoscode commented on Apr 10, 2020

    @fabiosantoscode
    Collaborator

    I want to do something akin to that as a final solution to this. Instead of keeping comments in the tokens, the tokens would contain a hand-wavy reference to an array of comments. If their related nodes were deleted, their respective comments could simply appear out of place.

    Comments have multiple users though. People who want to display licenses in their minified output, and people who are going to pass Terser output to another compiler and need the comment placement to be surgical. Hard to please both, and I'm still thinking of the best way to do that.

  9. LongTengDao commented on Apr 10, 2020

    @LongTengDao
    ContributorAuthor

    If you compile binary code, you don't write the license onto the binary. Nobody is reading it! You need to specify licenses separately, ...
    Minified JS should be the same right?

    Oh, I think you are right!

  10. fastfasterfastest commented on Apr 10, 2020

    @fastfasterfastest

    If you are going to do it within terser, maybe something a'la the name-cache... a comments-cache into which terser stashes certain comments encountered. The certain comments that would be stashed could e.g. be comments containing @preserve or @license or, better, specified by a regex option. The comments cache json file would be appended to and populated with an object for each comment, with properties such as comment itself, file/path name, line number, whether the node the comments was attached to was discarded by the compressor, etc.
    The comments cache json file can then be used post-minification, e.g. to append the minification output with (possibly a sub-set of) comments out of the cache.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugformatIssue in the code output step

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions