@@ -11,14 +11,16 @@ class JavaScriptPrintingOptions {
1111 final bool utf8;
1212 final bool shouldCompressOutput;
1313 final bool minifyLocalVariables;
14+ final bool minifyStatementLabels;
1415 final bool preferSemicolonToNewlineInMinifiedOutput;
1516
1617 const JavaScriptPrintingOptions ({
1718 this .utf8 = false ,
18- this .shouldCompressOutput = false ,
19- this .minifyLocalVariables = false ,
19+ bool minify = false ,
2020 this .preferSemicolonToNewlineInMinifiedOutput = false ,
21- });
21+ }) : shouldCompressOutput = minify,
22+ minifyLocalVariables = minify,
23+ minifyStatementLabels = minify;
2224}
2325
2426/// An environment in which JavaScript printing is done. Provides emitting of
@@ -89,6 +91,7 @@ class Printer implements NodeVisitor<void> {
8991 final bool shouldCompressOutput;
9092 final DanglingElseVisitor danglingElseVisitor;
9193 final LocalNamer localNamer;
94+ final _LabelNamer _labelNamer;
9295 final bool isDebugContext;
9396
9497 int _charCount = 0 ;
@@ -140,10 +143,10 @@ class Printer implements NodeVisitor<void> {
140143 : isDebugContext = context.isDebugContext,
141144 shouldCompressOutput = options.shouldCompressOutput,
142145 danglingElseVisitor = DanglingElseVisitor (context),
143- localNamer = determineRenamer (
144- options.shouldCompressOutput,
145- options.minifyLocalVariables ,
146- );
146+ localNamer = options.minifyLocalVariables
147+ ? MinifyRenamer ()
148+ : IdentityNamer () ,
149+ _labelNamer = _LabelNamer (options.minifyStatementLabels );
147150
148151 static LocalNamer determineRenamer (
149152 bool shouldCompressOutput,
@@ -577,7 +580,7 @@ class Printer implements NodeVisitor<void> {
577580 if (node.targetLabel == null ) {
578581 outIndent ('continue' );
579582 } else {
580- outIndent ('continue ${node .targetLabel }' );
583+ outIndent ('continue ${_labelNamer . mapLabelName ( node .targetLabel !) }' );
581584 }
582585 outSemicolonLn ();
583586 }
@@ -587,7 +590,7 @@ class Printer implements NodeVisitor<void> {
587590 if (node.targetLabel == null ) {
588591 outIndent ('break' );
589592 } else {
590- outIndent ('break ${node .targetLabel }' );
593+ outIndent ('break ${_labelNamer . mapLabelName ( node .targetLabel !) }' );
591594 }
592595 outSemicolonLn ();
593596 }
@@ -724,7 +727,7 @@ class Printer implements NodeVisitor<void> {
724727
725728 @override
726729 void visitLabeledStatement (LabeledStatement node) {
727- outIndent ('${node .label }:' );
730+ outIndent ('${_labelNamer . mapLabelName ( node .label ) }:' );
728731 blockBody (node.body, needsSeparation: false , needsNewline: true );
729732 }
730733
@@ -740,7 +743,7 @@ class Printer implements NodeVisitor<void> {
740743 newAtStatementBegin: false ,
741744 );
742745 }
743- localNamer. enterScope (vars);
746+ _enterFunctionScope (vars);
744747 out ('(' );
745748 visitCommaSeparated (
746749 fun.params,
@@ -771,10 +774,20 @@ class Printer implements NodeVisitor<void> {
771774 shouldIndent: false ,
772775 needsNewline: false ,
773776 );
774- localNamer. leaveScope ();
777+ _exitFunctionScope ();
775778 return closingPosition;
776779 }
777780
781+ void _enterFunctionScope (VarCollector vars) {
782+ localNamer.enterScope (vars);
783+ _labelNamer.enterFunction ();
784+ }
785+
786+ void _exitFunctionScope () {
787+ _labelNamer.exitFunction ();
788+ localNamer.leaveScope ();
789+ }
790+
778791 @override
779792 void visitFunctionDeclaration (FunctionDeclaration declaration) {
780793 VarCollector vars = VarCollector ();
@@ -1393,7 +1406,7 @@ class Printer implements NodeVisitor<void> {
13931406
13941407 int arrowFunctionOut (ArrowFunction fun, VarCollector vars) {
13951408 // TODO: support static, get/set, async, and generators.
1396- localNamer. enterScope (vars);
1409+ _enterFunctionScope (vars);
13971410 final List <Parameter > params = fun.params;
13981411 if (params.length == 1 && _isIdentifierParameter (params.first)) {
13991412 visitNestedExpression (
@@ -1438,7 +1451,7 @@ class Printer implements NodeVisitor<void> {
14381451 if (needsParens) out (')' );
14391452 closingPosition = _charCount;
14401453 }
1441- localNamer. leaveScope ();
1454+ _exitFunctionScope ();
14421455 return closingPosition;
14431456 }
14441457
@@ -1637,7 +1650,7 @@ class Printer implements NodeVisitor<void> {
16371650 int methodOut (MethodDefinition node, VarCollector vars) {
16381651 // TODO: support static, get/set, async, and generators.
16391652 Fun fun = node.function;
1640- localNamer. enterScope (vars);
1653+ _enterFunctionScope (vars);
16411654 out ('(' );
16421655 visitCommaSeparated (
16431656 fun.params,
@@ -1652,7 +1665,7 @@ class Printer implements NodeVisitor<void> {
16521665 shouldIndent: false ,
16531666 needsNewline: false ,
16541667 );
1655- localNamer. leaveScope ();
1668+ _exitFunctionScope ();
16561669 return closingPosition;
16571670 }
16581671
@@ -2139,6 +2152,42 @@ class MinifyRenamer implements LocalNamer {
21392152 }
21402153}
21412154
2155+ class _LabelNamer {
2156+ final bool renameLabels;
2157+
2158+ Map <String , String > _renamings = {};
2159+
2160+ final List <Map <String , String >> _outerScopes = [];
2161+
2162+ _LabelNamer (this .renameLabels);
2163+
2164+ String mapLabelName (String name) {
2165+ if (! renameLabels) return name;
2166+ return _renamings[name] ?? = _newLabelName (_renamings, name);
2167+ }
2168+
2169+ static String _newLabelName (Map <String , String > renamings, String name) {
2170+ assert (! renamings.containsKey (name));
2171+ int index = renamings.length;
2172+ if (index < 26 ) return String .fromCharCode (index + 'A' .codeUnitAt (0 ));
2173+ index -= 26 ;
2174+ if (index < 26 ) return String .fromCharCode (index + 'a' .codeUnitAt (0 ));
2175+ index -= 26 ;
2176+ return 'L$index ' ;
2177+ }
2178+
2179+ void enterFunction () {
2180+ if (! renameLabels) return ;
2181+ _outerScopes.add (_renamings);
2182+ _renamings = {};
2183+ }
2184+
2185+ void exitFunction () {
2186+ if (! renameLabels) return ;
2187+ _renamings = _outerScopes.removeLast ();
2188+ }
2189+ }
2190+
21422191/// Information pertaining the enter and exit callbacks for [node] .
21432192class EnterExitNode {
21442193 final EnterExitNode ? parent;
0 commit comments