How does Google Closure Compiler handle quotes (string literals)?

雨燕双飞 提交于 2019-12-01 00:40:48

It is often stated that (or asked why) Google Closure Compiler (GCC) replaces single quotes with double-quotes (even when the compilation_level is set to WHITESPACE_ONLY !!!):

example xmp_1.js:

alert('Hello world!');           // output: alert("Hello world!");

However... this is only half of 'the truth', because:

example xmp_2.js:

alert('Hello "world"!');         // output: alert('Hello "world"!');
                                 //  *NOT*: alert("Hello \"world\"!");

GCC is essentially a 'your raw javascript' to 'smaller (and more efficient) javascript' translator: so it does not 'blindly' replace single quotes with double quotes, but tries to choose an 'optimal quote-character' (after all.. one of the primary goals is to 'mini-fy' the script).

From the source-code (CompilerOptions.java) and this issue-report one can learn that:

If the string contains more single quotes than double quotes then the compiler will wrap the string using double quotes and vice versa.
If the string contains no quotes or an equal number of single and double quotes, then the compiler will default to using double quotes.

Like this example xmp_3.js:

alert('Hello "w\'orld"!');       // output: alert('Hello "w\'orld"!');
alert('Hello "w\'o\'rld"!');     //         alert("Hello \"w'o'rld\"!");

Note how the above xmp_3 results in a 'mixed' output that uses both ' and " as outer quotation: the optimal choice followed by the default (when it didn't matter).

How to change/override the default double quotes to single quotes?

As it turned out there are some serious legitimate real-world cases where defaulting to single-quotes would have been better. As explained in the issue 836 (from Oct 8, 2012) referenced above:

The FT web app (app.ft.com) and the Economist app for Playbook deliver JavaScript updates to the client along with other resources by transmitting them as part of a JSON-encoded object. JSON uses double quotes natively, so all the double quotes in the compiled JavaScript need to be escaped. This inflates the size of the FT web app's JS by about 20kB when transmitting a large update.

The reporter of the issue came with a gift: a patch that added the option prefer_single_quotes to change the default quote-character from double quote to single quote.

This issue was taken seriously enough that project member Santos considered changing the default double quote to single quote ('and see if anybody complains').. TWICE (also after the reporter/patch-contributer stated that he implemented it as an option so that it wouldn't have any backward-compatibility consequences since 'someone might be relying on strings being output with double quotes for some bizarre reason').

However, about one week later the patch was accepted (r2258), another week later reworked (r2257) and on Oct 30, 2012 Santos reported back that the option could now be enabled with:
--formatting=SINGLE_QUOTES
(so a third option besides PRETTY_PRINT and PRINT_INPUT_DELIMITER for the formatting-key).
(Note: in the current source-code one can currently still find numerous references to 'prefer_single_quotes' as well.)

Usage:
If you (download and) use the (local java) application:

java -jar compiler.jar --js xmp_1.js --formatting SINGLE_QUOTES and you will see that: alert('Hello world!'); now compiles to alert('Hello world!');

However, at this time of writing, the Compiler Service API and UI (that most probably uses the API) located at http://closure-compiler.appspot.com, do not accept this third (new, although a year in existence) formatting-option: SINGLE_QUOTES and will throw an error:
17: Unknown formatting option single_quotes.

After digging (again) through the source, it seems (I'm not a Java-expert) that this is because jscomp/webservice/common/Protocol.java only accepts the older PRETTY_PRINT and PRINT_INPUT_DELIMITER

 * All the possible values for the FORMATTING key.
 */
public static enum FormattingKey implements ProtocolEnum {
  PRETTY_PRINT("pretty_print"),
  PRINT_INPUT_DELIMITER("print_input_delimiter"),
  ;

I will update this answer should this option become available in the API and/or UI.

Hope this helps and saves someone some time, since the only documentation and reference google can find about SINGLE_QUOTES is currently in this one issue 836 and some comments in the source. Now it has some explanation on SO (where I'd expect it).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!