From: Alex Lam S.L Date: Tue, 6 Apr 2021 13:34:27 +0000 (+0100) Subject: clean up `OutputStream` (#4842) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=231c3d7c840b622ef5564428ea7a2faf3901122e;p=UglifyJS.git clean up `OutputStream` (#4842) --- diff --git a/lib/output.js b/lib/output.js index fef57bce..e2009792 100644 --- a/lib/output.js +++ b/lib/output.js @@ -49,8 +49,6 @@ function is_some_comments(comment) { } function OutputStream(options) { - - var readonly = !options; options = defaults(options, { annotations : false, ascii_only : false, @@ -103,12 +101,47 @@ function OutputStream(options) { } } - var indentation = options.indent_start; - var current_col = 0; - var current_line = 1; - var current_pos = 0; - var OUTPUT = ""; + var OUTPUT; + var current_col; + var current_line; + var current_pos; + var has_parens; + var indentation; + var last; + var line_end; + var line_fixed; + var mappings; + var mapping_name; + var mapping_token; + var might_need_space; + var might_need_semicolon; + var need_newline_indented; + var need_space; + var newline_insert; + var stack; + + function reset() { + OUTPUT = ""; + current_col = 0; + current_line = 1; + current_pos = 0; + has_parens = false; + indentation = options.indent_start; + last = ""; + line_end = 0; + line_fixed = true; + mappings = options.source_map && []; + mapping_name = null; + mapping_token = null; + might_need_space = false; + might_need_semicolon = false; + need_newline_indented = false; + need_space = false; + newline_insert = -1; + stack = []; + } + reset(); var to_utf8 = options.ascii_only ? function(str, identifier) { if (identifier) str = str.replace(/[\ud800-\udbff][\udc00-\udfff]/g, function(ch) { return "\\u{" + (ch.charCodeAt(0) - 0xd7c0 << 10 | ch.charCodeAt(1) - 0xdc00).toString(16) + "}"; @@ -141,6 +174,25 @@ function OutputStream(options) { return j == 0 ? str : s + str.slice(j); }; + function quote_single(str) { + return "'" + str.replace(/\x27/g, "\\'") + "'"; + } + + function quote_double(str) { + return '"' + str.replace(/\x22/g, '\\"') + '"'; + } + + var quote_string = [ + function(str, quote, dq, sq) { + return dq > sq ? quote_single(str) : quote_double(str); + }, + quote_single, + quote_double, + function(str, quote) { + return quote == "'" ? quote_single(str) : quote_double(str); + }, + ][options.quote_style]; + function make_string(str, quote) { var dq = 0, sq = 0; str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g, function(s, i) { @@ -162,54 +214,11 @@ function OutputStream(options) { } return s; }); - function quote_single() { - return "'" + str.replace(/\x27/g, "\\'") + "'"; - } - function quote_double() { - return '"' + str.replace(/\x22/g, '\\"') + '"'; - } - str = to_utf8(str); - switch (options.quote_style) { - case 1: - return quote_single(); - case 2: - return quote_double(); - case 3: - return quote == "'" ? quote_single() : quote_double(); - default: - return dq > sq ? quote_single() : quote_double(); - } - } - - function encode_string(str, quote) { - var ret = make_string(str, quote); - if (options.inline_script) { - ret = ret.replace(/<\x2f(script)([>\/\t\n\f\r ])/gi, "<\\/$1$2"); - ret = ret.replace(/\x3c!--/g, "\\x3c!--"); - ret = ret.replace(/--\x3e/g, "--\\x3e"); - } - return ret; - } - - function make_name(name) { - name = name.toString(); - name = to_utf8(name, true); - return name; + return quote_string(to_utf8(str), quote, dq, sq); } /* -----[ beautification/minification ]----- */ - var has_parens = false; - var line_end = 0; - var line_fixed = true; - var might_need_space = false; - var might_need_semicolon = false; - var need_newline_indented = false; - var need_space = false; - var newline_insert = -1; - var last = ""; - var mapping_token, mapping_name, mappings = options.source_map && []; - var adjust_mappings = mappings ? function(line, col) { mappings.forEach(function(mapping) { mapping.line += line; @@ -351,14 +360,12 @@ function OutputStream(options) { print(repeat_string(" ", half ? indentation - (options.indent_level >> 1) : indentation)); } : noop; - var with_indent = options.beautify ? function(col, cont) { - if (col === true) col = next_indent(); + var with_indent = options.beautify ? function(cont) { var save_indentation = indentation; - indentation = col; - var ret = cont(); + indentation += options.indent_level; + cont(); indentation = save_indentation; - return ret; - } : function(col, cont) { return cont() }; + } : function(cont) { cont() }; var may_add_newline = options.max_line_len || options.preserve_line ? function() { fix_line(); @@ -387,41 +394,28 @@ function OutputStream(options) { print(";"); } - function next_indent() { - return indentation + options.indent_level; - } - function with_block(cont) { - var ret; print("{"); newline(); - with_indent(next_indent(), function() { - ret = cont(); - }); + with_indent(cont); indent(); print("}"); - return ret; } function with_parens(cont) { print("("); may_add_newline(); - //XXX: still nice to have that for argument lists - //var ret = with_indent(current_col, cont); - var ret = cont(); + cont(); may_add_newline(); print(")"); - return ret; } function with_square(cont) { print("["); may_add_newline(); - //var ret = with_indent(current_col, cont); - var ret = cont(); + cont(); may_add_newline(); print("]"); - return ret; } function comma() { @@ -553,12 +547,11 @@ function OutputStream(options) { if (OUTPUT.length > insert) newline_insert = insert; } - var stack = []; return { get : get, - toString : get, + reset : reset, indent : indent, - should_break : readonly ? noop : function() { + should_break : function() { return options.width && current_col - indentation >= options.width; }, has_parens : function() { return has_parens }, @@ -571,17 +564,21 @@ function OutputStream(options) { semicolon : semicolon, force_semicolon : force_semicolon, to_utf8 : to_utf8, - print_name : function(name) { print(make_name(name)) }, - print_string : function(str, quote) { print(encode_string(str, quote)) }, - next_indent : next_indent, + print_name : function(name) { print(to_utf8(name.toString(), true)) }, + print_string : options.inline_script ? function(str, quote) { + str = make_string(str, quote).replace(/<\x2f(script)([>\/\t\n\f\r ])/gi, "<\\/$1$2"); + print(str.replace(/\x3c!--/g, "\\x3c!--").replace(/--\x3e/g, "--\\x3e")); + } : function(str, quote) { + print(make_string(str, quote)); + }, with_indent : with_indent, with_block : with_block, with_parens : with_parens, with_square : with_square, add_mapping : add_mapping, option : function(opt) { return options[opt] }, - prepend_comments: readonly ? noop : prepend_comments, - append_comments : readonly || comment_filter === return_false ? noop : append_comments, + prepend_comments: prepend_comments, + append_comments : comment_filter === return_false ? noop : append_comments, line : function() { return current_line }, col : function() { return current_col }, pos : function() { return current_pos }, @@ -629,10 +626,21 @@ function OutputStream(options) { stream.append_comments(self); } }); + var readonly = OutputStream({ + inline_script: false, + }); + readonly.prepend_comments = noop; + readonly.should_break = return_false; AST_Node.DEFMETHOD("print_to_string", function(options) { - var s = OutputStream(options); - this.print(s); - return s.get(); + if (options) { + var stream = OutputStream(options); + this.print(stream); + return stream.get(); + } + this.print(readonly); + var str = readonly.get(); + readonly.reset(); + return str; }); /* -----[ PARENTHESES ]----- */ @@ -915,7 +923,7 @@ function OutputStream(options) { }); function print_braced_empty(self, output) { output.print("{"); - output.with_indent(output.next_indent(), function() { + output.with_indent(function() { output.append_comments(self, true); }); output.print("}"); diff --git a/test/ufuzz/index.js b/test/ufuzz/index.js index 7eadc9ab..5c6c2625 100644 --- a/test/ufuzz/index.js +++ b/test/ufuzz/index.js @@ -206,6 +206,7 @@ var VALUES = [ ]; VALUES = VALUES.concat(VALUES); VALUES = VALUES.concat(VALUES); +VALUES = VALUES.concat(VALUES); if (SUPPORT.bigint) VALUES = VALUES.concat([ "(!0o644n)", "([3n][0] > 2)", @@ -215,6 +216,7 @@ if (SUPPORT.bigint) VALUES = VALUES.concat([ VALUES = VALUES.concat(VALUES); VALUES = VALUES.concat(VALUES); VALUES = VALUES.concat(VALUES); +VALUES = VALUES.concat(VALUES); VALUES.push("import.meta"); var BINARY_OPS = [