browser/devtools/shared/Jsbeautify.jsm

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/browser/devtools/shared/Jsbeautify.jsm	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1303 @@
     1.4 +/*jslint onevar: false, plusplus: false */
     1.5 +/*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
     1.6 +/*
     1.7 +
     1.8 + JS Beautifier
     1.9 +---------------
    1.10 +
    1.11 +
    1.12 +  Written by Einar Lielmanis, <einar@jsbeautifier.org>
    1.13 +      http://jsbeautifier.org/
    1.14 +
    1.15 +  Originally converted to javascript by Vital, <vital76@gmail.com>
    1.16 +  "End braces on own line" added by Chris J. Shull, <chrisjshull@gmail.com>
    1.17 +
    1.18 +  You are free to use this in any way you want, in case you find this useful or working for you.
    1.19 +
    1.20 +  Usage:
    1.21 +    js_beautify(js_source_text);
    1.22 +    js_beautify(js_source_text, options);
    1.23 +
    1.24 +  The options are:
    1.25 +    indent_size (default 4)          - indentation size,
    1.26 +    indent_char (default space)      - character to indent with,
    1.27 +    preserve_newlines (default true) - whether existing line breaks should be preserved,
    1.28 +    max_preserve_newlines (default unlimited) - maximum number of line breaks to be preserved in one chunk,
    1.29 +
    1.30 +    jslint_happy (default false) - if true, then jslint-stricter mode is enforced.
    1.31 +
    1.32 +            jslint_happy   !jslint_happy
    1.33 +            ---------------------------------
    1.34 +             function ()      function()
    1.35 +
    1.36 +    brace_style (default "collapse") - "collapse" | "expand" | "end-expand" | "expand-strict"
    1.37 +            put braces on the same line as control statements (default), or put braces on own line (Allman / ANSI style), or just put end braces on own line.
    1.38 +
    1.39 +            expand-strict: put brace on own line even in such cases:
    1.40 +
    1.41 +                var a =
    1.42 +                {
    1.43 +                    a: 5,
    1.44 +                    b: 6
    1.45 +                }
    1.46 +            This mode may break your scripts - e.g "return { a: 1 }" will be broken into two lines, so beware.
    1.47 +
    1.48 +    space_before_conditional (default true) - should the space before conditional statement be added, "if(true)" vs "if (true)",
    1.49 +
    1.50 +    unescape_strings (default false) - should printable characters in strings encoded in \xNN notation be unescaped, "example" vs "\x65\x78\x61\x6d\x70\x6c\x65"
    1.51 +
    1.52 +    e.g
    1.53 +
    1.54 +    js_beautify(js_source_text, {
    1.55 +      'indent_size': 1,
    1.56 +      'indent_char': '\t'
    1.57 +    });
    1.58 +
    1.59 +
    1.60 +*/
    1.61 +
    1.62 +this.EXPORTED_SYMBOLS = ["js_beautify"];
    1.63 +
    1.64 +this.js_beautify = function js_beautify(js_source_text, options) {
    1.65 +
    1.66 +    var input, output, token_text, last_type, last_text, last_last_text, last_word, flags, flag_store, indent_string;
    1.67 +    var whitespace, wordchar, punct, parser_pos, line_starters, digits;
    1.68 +    var prefix, token_type, do_block_just_closed;
    1.69 +    var wanted_newline, just_added_newline, n_newlines;
    1.70 +    var preindent_string = '';
    1.71 +
    1.72 +
    1.73 +    // Some interpreters have unexpected results with foo = baz || bar;
    1.74 +    options = options ? options : {};
    1.75 +
    1.76 +    var opt_brace_style;
    1.77 +
    1.78 +    // compatibility
    1.79 +    if (options.space_after_anon_function !== undefined && options.jslint_happy === undefined) {
    1.80 +        options.jslint_happy = options.space_after_anon_function;
    1.81 +    }
    1.82 +    if (options.braces_on_own_line !== undefined) { //graceful handling of deprecated option
    1.83 +        opt_brace_style = options.braces_on_own_line ? "expand" : "collapse";
    1.84 +    }
    1.85 +    opt_brace_style = options.brace_style ? options.brace_style : (opt_brace_style ? opt_brace_style : "collapse");
    1.86 +
    1.87 +
    1.88 +    var opt_indent_size = options.indent_size ? options.indent_size : 4;
    1.89 +    var opt_indent_char = options.indent_char ? options.indent_char : ' ';
    1.90 +    var opt_preserve_newlines = typeof options.preserve_newlines === 'undefined' ? true : options.preserve_newlines;
    1.91 +    var opt_max_preserve_newlines = typeof options.max_preserve_newlines === 'undefined' ? false : options.max_preserve_newlines;
    1.92 +    var opt_jslint_happy = options.jslint_happy === 'undefined' ? false : options.jslint_happy;
    1.93 +    var opt_keep_array_indentation = typeof options.keep_array_indentation === 'undefined' ? false : options.keep_array_indentation;
    1.94 +    var opt_space_before_conditional = typeof options.space_before_conditional === 'undefined' ? true : options.space_before_conditional;
    1.95 +    var opt_indent_case = typeof options.indent_case === 'undefined' ? false : options.indent_case;
    1.96 +    var opt_unescape_strings = typeof options.unescape_strings === 'undefined' ? false : options.unescape_strings;
    1.97 +
    1.98 +    just_added_newline = false;
    1.99 +
   1.100 +    // cache the source's length.
   1.101 +    var input_length = js_source_text.length;
   1.102 +
   1.103 +    function trim_output(eat_newlines) {
   1.104 +        eat_newlines = typeof eat_newlines === 'undefined' ? false : eat_newlines;
   1.105 +        while (output.length && (output[output.length - 1] === ' '
   1.106 +            || output[output.length - 1] === indent_string
   1.107 +            || output[output.length - 1] === preindent_string
   1.108 +            || (eat_newlines && (output[output.length - 1] === '\n' || output[output.length - 1] === '\r')))) {
   1.109 +            output.pop();
   1.110 +        }
   1.111 +    }
   1.112 +
   1.113 +    function trim(s) {
   1.114 +        return s.replace(/^\s\s*|\s\s*$/, '');
   1.115 +    }
   1.116 +
   1.117 +    // we could use just string.split, but
   1.118 +    // IE doesn't like returning empty strings
   1.119 +    function split_newlines(s) {
   1.120 +        return s.split(/\x0d\x0a|\x0a/);
   1.121 +    }
   1.122 +
   1.123 +    function force_newline() {
   1.124 +        var old_keep_array_indentation = opt_keep_array_indentation;
   1.125 +        opt_keep_array_indentation = false;
   1.126 +        print_newline();
   1.127 +        opt_keep_array_indentation = old_keep_array_indentation;
   1.128 +    }
   1.129 +
   1.130 +    function print_newline(ignore_repeated) {
   1.131 +
   1.132 +        flags.eat_next_space = false;
   1.133 +        if (opt_keep_array_indentation && is_array(flags.mode)) {
   1.134 +            return;
   1.135 +        }
   1.136 +
   1.137 +        ignore_repeated = typeof ignore_repeated === 'undefined' ? true : ignore_repeated;
   1.138 +
   1.139 +        flags.if_line = false;
   1.140 +        trim_output();
   1.141 +
   1.142 +        if (!output.length) {
   1.143 +            return; // no newline on start of file
   1.144 +        }
   1.145 +
   1.146 +        if (output[output.length - 1] !== "\n" || !ignore_repeated) {
   1.147 +            just_added_newline = true;
   1.148 +            output.push("\n");
   1.149 +        }
   1.150 +        if (preindent_string) {
   1.151 +            output.push(preindent_string);
   1.152 +        }
   1.153 +        for (var i = 0; i < flags.indentation_level; i += 1) {
   1.154 +            output.push(indent_string);
   1.155 +        }
   1.156 +        if (flags.var_line && flags.var_line_reindented) {
   1.157 +            output.push(indent_string); // skip space-stuffing, if indenting with a tab
   1.158 +        }
   1.159 +        if (flags.case_body) {
   1.160 +            output.push(indent_string);
   1.161 +        }
   1.162 +    }
   1.163 +
   1.164 +
   1.165 +
   1.166 +    function print_single_space() {
   1.167 +
   1.168 +        if (last_type === 'TK_COMMENT') {
   1.169 +            return print_newline();
   1.170 +        }
   1.171 +        if (flags.eat_next_space) {
   1.172 +            flags.eat_next_space = false;
   1.173 +            return;
   1.174 +        }
   1.175 +        var last_output = ' ';
   1.176 +        if (output.length) {
   1.177 +            last_output = output[output.length - 1];
   1.178 +        }
   1.179 +        if (last_output !== ' ' && last_output !== '\n' && last_output !== indent_string) { // prevent occassional duplicate space
   1.180 +            output.push(' ');
   1.181 +        }
   1.182 +    }
   1.183 +
   1.184 +
   1.185 +    function print_token() {
   1.186 +        just_added_newline = false;
   1.187 +        flags.eat_next_space = false;
   1.188 +        output.push(token_text);
   1.189 +    }
   1.190 +
   1.191 +    function indent() {
   1.192 +        flags.indentation_level += 1;
   1.193 +    }
   1.194 +
   1.195 +
   1.196 +    function remove_indent() {
   1.197 +        if (output.length && output[output.length - 1] === indent_string) {
   1.198 +            output.pop();
   1.199 +        }
   1.200 +    }
   1.201 +
   1.202 +    function set_mode(mode) {
   1.203 +        if (flags) {
   1.204 +            flag_store.push(flags);
   1.205 +        }
   1.206 +        flags = {
   1.207 +            previous_mode: flags ? flags.mode : 'BLOCK',
   1.208 +            mode: mode,
   1.209 +            var_line: false,
   1.210 +            var_line_tainted: false,
   1.211 +            var_line_reindented: false,
   1.212 +            in_html_comment: false,
   1.213 +            if_line: false,
   1.214 +            in_case_statement: false, // switch(..){ INSIDE HERE }
   1.215 +            in_case: false, // we're on the exact line with "case 0:"
   1.216 +            case_body: false, // the indented case-action block
   1.217 +            eat_next_space: false,
   1.218 +            indentation_baseline: -1,
   1.219 +            indentation_level: (flags ? flags.indentation_level + (flags.case_body ? 1 : 0) + ((flags.var_line && flags.var_line_reindented) ? 1 : 0) : 0),
   1.220 +            ternary_depth: 0
   1.221 +        };
   1.222 +    }
   1.223 +
   1.224 +    function is_array(mode) {
   1.225 +        return mode === '[EXPRESSION]' || mode === '[INDENTED-EXPRESSION]';
   1.226 +    }
   1.227 +
   1.228 +    function is_expression(mode) {
   1.229 +        return in_array(mode, ['[EXPRESSION]', '(EXPRESSION)', '(FOR-EXPRESSION)', '(COND-EXPRESSION)']);
   1.230 +    }
   1.231 +
   1.232 +    function restore_mode() {
   1.233 +        do_block_just_closed = flags.mode === 'DO_BLOCK';
   1.234 +        if (flag_store.length > 0) {
   1.235 +            var mode = flags.mode;
   1.236 +            flags = flag_store.pop();
   1.237 +            flags.previous_mode = mode;
   1.238 +        }
   1.239 +    }
   1.240 +
   1.241 +    function all_lines_start_with(lines, c) {
   1.242 +        for (var i = 0; i < lines.length; i++) {
   1.243 +            var line = trim(lines[i]);
   1.244 +            if (line.charAt(0) !== c) {
   1.245 +                return false;
   1.246 +            }
   1.247 +        }
   1.248 +        return true;
   1.249 +    }
   1.250 +
   1.251 +    function is_special_word(word) {
   1.252 +        return in_array(word, ['case', 'return', 'do', 'if', 'throw', 'else']);
   1.253 +    }
   1.254 +
   1.255 +    function in_array(what, arr) {
   1.256 +        for (var i = 0; i < arr.length; i += 1) {
   1.257 +            if (arr[i] === what) {
   1.258 +                return true;
   1.259 +            }
   1.260 +        }
   1.261 +        return false;
   1.262 +    }
   1.263 +
   1.264 +    function look_up(exclude) {
   1.265 +        var local_pos = parser_pos;
   1.266 +        var c = input.charAt(local_pos);
   1.267 +        while (in_array(c, whitespace) && c !== exclude) {
   1.268 +            local_pos++;
   1.269 +            if (local_pos >= input_length) {
   1.270 +                return 0;
   1.271 +            }
   1.272 +            c = input.charAt(local_pos);
   1.273 +        }
   1.274 +        return c;
   1.275 +    }
   1.276 +
   1.277 +    function get_next_token() {
   1.278 +        var i;
   1.279 +        var resulting_string;
   1.280 +
   1.281 +        n_newlines = 0;
   1.282 +
   1.283 +        if (parser_pos >= input_length) {
   1.284 +            return ['', 'TK_EOF'];
   1.285 +        }
   1.286 +
   1.287 +        wanted_newline = false;
   1.288 +
   1.289 +        var c = input.charAt(parser_pos);
   1.290 +        parser_pos += 1;
   1.291 +
   1.292 +
   1.293 +        var keep_whitespace = opt_keep_array_indentation && is_array(flags.mode);
   1.294 +
   1.295 +        if (keep_whitespace) {
   1.296 +
   1.297 +            //
   1.298 +            // slight mess to allow nice preservation of array indentation and reindent that correctly
   1.299 +            // first time when we get to the arrays:
   1.300 +            // var a = [
   1.301 +            // ....'something'
   1.302 +            // we make note of whitespace_count = 4 into flags.indentation_baseline
   1.303 +            // so we know that 4 whitespaces in original source match indent_level of reindented source
   1.304 +            //
   1.305 +            // and afterwards, when we get to
   1.306 +            //    'something,
   1.307 +            // .......'something else'
   1.308 +            // we know that this should be indented to indent_level + (7 - indentation_baseline) spaces
   1.309 +            //
   1.310 +            var whitespace_count = 0;
   1.311 +
   1.312 +            while (in_array(c, whitespace)) {
   1.313 +
   1.314 +                if (c === "\n") {
   1.315 +                    trim_output();
   1.316 +                    output.push("\n");
   1.317 +                    just_added_newline = true;
   1.318 +                    whitespace_count = 0;
   1.319 +                } else {
   1.320 +                    if (c === '\t') {
   1.321 +                        whitespace_count += 4;
   1.322 +                    } else if (c === '\r') {
   1.323 +                        // nothing
   1.324 +                    } else {
   1.325 +                        whitespace_count += 1;
   1.326 +                    }
   1.327 +                }
   1.328 +
   1.329 +                if (parser_pos >= input_length) {
   1.330 +                    return ['', 'TK_EOF'];
   1.331 +                }
   1.332 +
   1.333 +                c = input.charAt(parser_pos);
   1.334 +                parser_pos += 1;
   1.335 +
   1.336 +            }
   1.337 +            if (flags.indentation_baseline === -1) {
   1.338 +                flags.indentation_baseline = whitespace_count;
   1.339 +            }
   1.340 +
   1.341 +            if (just_added_newline) {
   1.342 +                for (i = 0; i < flags.indentation_level + 1; i += 1) {
   1.343 +                    output.push(indent_string);
   1.344 +                }
   1.345 +                if (flags.indentation_baseline !== -1) {
   1.346 +                    for (i = 0; i < whitespace_count - flags.indentation_baseline; i++) {
   1.347 +                        output.push(' ');
   1.348 +                    }
   1.349 +                }
   1.350 +            }
   1.351 +
   1.352 +        } else {
   1.353 +            while (in_array(c, whitespace)) {
   1.354 +
   1.355 +                if (c === "\n") {
   1.356 +                    n_newlines += ((opt_max_preserve_newlines) ? (n_newlines <= opt_max_preserve_newlines) ? 1 : 0 : 1);
   1.357 +                }
   1.358 +
   1.359 +
   1.360 +                if (parser_pos >= input_length) {
   1.361 +                    return ['', 'TK_EOF'];
   1.362 +                }
   1.363 +
   1.364 +                c = input.charAt(parser_pos);
   1.365 +                parser_pos += 1;
   1.366 +
   1.367 +            }
   1.368 +
   1.369 +            if (opt_preserve_newlines) {
   1.370 +                if (n_newlines > 1) {
   1.371 +                    for (i = 0; i < n_newlines; i += 1) {
   1.372 +                        print_newline(i === 0);
   1.373 +                        just_added_newline = true;
   1.374 +                    }
   1.375 +                }
   1.376 +            }
   1.377 +            wanted_newline = n_newlines > 0;
   1.378 +        }
   1.379 +
   1.380 +
   1.381 +        if (in_array(c, wordchar)) {
   1.382 +            if (parser_pos < input_length) {
   1.383 +                while (in_array(input.charAt(parser_pos), wordchar)) {
   1.384 +                    c += input.charAt(parser_pos);
   1.385 +                    parser_pos += 1;
   1.386 +                    if (parser_pos === input_length) {
   1.387 +                        break;
   1.388 +                    }
   1.389 +                }
   1.390 +            }
   1.391 +
   1.392 +            // small and surprisingly unugly hack for 1E-10 representation
   1.393 +            if (parser_pos !== input_length && c.match(/^[0-9]+[Ee]$/) && (input.charAt(parser_pos) === '-' || input.charAt(parser_pos) === '+')) {
   1.394 +
   1.395 +                var sign = input.charAt(parser_pos);
   1.396 +                parser_pos += 1;
   1.397 +
   1.398 +                var t = get_next_token();
   1.399 +                c += sign + t[0];
   1.400 +                return [c, 'TK_WORD'];
   1.401 +            }
   1.402 +
   1.403 +            if (c === 'in') { // hack for 'in' operator
   1.404 +                return [c, 'TK_OPERATOR'];
   1.405 +            }
   1.406 +            if (wanted_newline && last_type !== 'TK_OPERATOR'
   1.407 +                && last_type !== 'TK_EQUALS'
   1.408 +                && !flags.if_line && (opt_preserve_newlines || last_text !== 'var')) {
   1.409 +                print_newline();
   1.410 +            }
   1.411 +            return [c, 'TK_WORD'];
   1.412 +        }
   1.413 +
   1.414 +        if (c === '(' || c === '[') {
   1.415 +            return [c, 'TK_START_EXPR'];
   1.416 +        }
   1.417 +
   1.418 +        if (c === ')' || c === ']') {
   1.419 +            return [c, 'TK_END_EXPR'];
   1.420 +        }
   1.421 +
   1.422 +        if (c === '{') {
   1.423 +            return [c, 'TK_START_BLOCK'];
   1.424 +        }
   1.425 +
   1.426 +        if (c === '}') {
   1.427 +            return [c, 'TK_END_BLOCK'];
   1.428 +        }
   1.429 +
   1.430 +        if (c === ';') {
   1.431 +            return [c, 'TK_SEMICOLON'];
   1.432 +        }
   1.433 +
   1.434 +        if (c === '/') {
   1.435 +            var comment = '';
   1.436 +            // peek for comment /* ... */
   1.437 +            var inline_comment = true;
   1.438 +            if (input.charAt(parser_pos) === '*') {
   1.439 +                parser_pos += 1;
   1.440 +                if (parser_pos < input_length) {
   1.441 +                    while (parser_pos < input_length &&
   1.442 +                        ! (input.charAt(parser_pos) === '*' && input.charAt(parser_pos + 1) && input.charAt(parser_pos + 1) === '/')) {
   1.443 +                        c = input.charAt(parser_pos);
   1.444 +                        comment += c;
   1.445 +                        if (c === "\n" || c === "\r") {
   1.446 +                            inline_comment = false;
   1.447 +                        }
   1.448 +                        parser_pos += 1;
   1.449 +                        if (parser_pos >= input_length) {
   1.450 +                            break;
   1.451 +                        }
   1.452 +                    }
   1.453 +                }
   1.454 +                parser_pos += 2;
   1.455 +                if (inline_comment && n_newlines === 0) {
   1.456 +                    return ['/*' + comment + '*/', 'TK_INLINE_COMMENT'];
   1.457 +                } else {
   1.458 +                    return ['/*' + comment + '*/', 'TK_BLOCK_COMMENT'];
   1.459 +                }
   1.460 +            }
   1.461 +            // peek for comment // ...
   1.462 +            if (input.charAt(parser_pos) === '/') {
   1.463 +                comment = c;
   1.464 +                while (input.charAt(parser_pos) !== '\r' && input.charAt(parser_pos) !== '\n') {
   1.465 +                    comment += input.charAt(parser_pos);
   1.466 +                    parser_pos += 1;
   1.467 +                    if (parser_pos >= input_length) {
   1.468 +                        break;
   1.469 +                    }
   1.470 +                }
   1.471 +                if (wanted_newline) {
   1.472 +                    print_newline();
   1.473 +                }
   1.474 +                return [comment, 'TK_COMMENT'];
   1.475 +            }
   1.476 +
   1.477 +        }
   1.478 +
   1.479 +        if (c === "'" || // string
   1.480 +        c === '"' || // string
   1.481 +        (c === '/' &&
   1.482 +            ((last_type === 'TK_WORD' && is_special_word(last_text)) ||
   1.483 +                (last_text === ')' && in_array(flags.previous_mode, ['(COND-EXPRESSION)', '(FOR-EXPRESSION)'])) ||
   1.484 +                (last_type === 'TK_COMMA' || last_type === 'TK_COMMENT' || last_type === 'TK_START_EXPR' || last_type === 'TK_START_BLOCK' || last_type === 'TK_END_BLOCK' || last_type === 'TK_OPERATOR' || last_type === 'TK_EQUALS' || last_type === 'TK_EOF' || last_type === 'TK_SEMICOLON')))) { // regexp
   1.485 +            var sep = c;
   1.486 +            var esc = false;
   1.487 +            var esc1 = 0;
   1.488 +            var esc2 = 0;
   1.489 +            resulting_string = c;
   1.490 +
   1.491 +            if (parser_pos < input_length) {
   1.492 +                if (sep === '/') {
   1.493 +                    //
   1.494 +                    // handle regexp separately...
   1.495 +                    //
   1.496 +                    var in_char_class = false;
   1.497 +                    while (esc || in_char_class || input.charAt(parser_pos) !== sep) {
   1.498 +                        resulting_string += input.charAt(parser_pos);
   1.499 +                        if (!esc) {
   1.500 +                            esc = input.charAt(parser_pos) === '\\';
   1.501 +                            if (input.charAt(parser_pos) === '[') {
   1.502 +                                in_char_class = true;
   1.503 +                            } else if (input.charAt(parser_pos) === ']') {
   1.504 +                                in_char_class = false;
   1.505 +                            }
   1.506 +                        } else {
   1.507 +                            esc = false;
   1.508 +                        }
   1.509 +                        parser_pos += 1;
   1.510 +                        if (parser_pos >= input_length) {
   1.511 +                            // incomplete string/rexp when end-of-file reached.
   1.512 +                            // bail out with what had been received so far.
   1.513 +                            return [resulting_string, 'TK_STRING'];
   1.514 +                        }
   1.515 +                    }
   1.516 +
   1.517 +                } else {
   1.518 +                    //
   1.519 +                    // and handle string also separately
   1.520 +                    //
   1.521 +                    while (esc || input.charAt(parser_pos) !== sep) {
   1.522 +                        resulting_string += input.charAt(parser_pos);
   1.523 +                        if (esc1 && esc1 >= esc2) {
   1.524 +                            esc1 = parseInt(resulting_string.substr(-esc2), 16);
   1.525 +                            if (esc1 && esc1 >= 0x20 && esc1 <= 0x7e) {
   1.526 +                                esc1 = String.fromCharCode(esc1);
   1.527 +                                resulting_string = resulting_string.substr(0, resulting_string.length - esc2 - 2) + (((esc1 === sep) || (esc1 === '\\')) ? '\\' : '') + esc1;
   1.528 +                            }
   1.529 +                            esc1 = 0;
   1.530 +                        }
   1.531 +                        if (esc1) {
   1.532 +                            esc1++;
   1.533 +                        } else if (!esc) {
   1.534 +                            esc = input.charAt(parser_pos) === '\\';
   1.535 +                        } else {
   1.536 +                            esc = false;
   1.537 +                            if (opt_unescape_strings) {
   1.538 +                                if (input.charAt(parser_pos) === 'x') {
   1.539 +                                    esc1++;
   1.540 +                                    esc2 = 2;
   1.541 +                                } else if (input.charAt(parser_pos) === 'u') {
   1.542 +                                    esc1++;
   1.543 +                                    esc2 = 4;
   1.544 +                                }
   1.545 +                            }
   1.546 +                        }
   1.547 +                        parser_pos += 1;
   1.548 +                        if (parser_pos >= input_length) {
   1.549 +                            // incomplete string/rexp when end-of-file reached.
   1.550 +                            // bail out with what had been received so far.
   1.551 +                            return [resulting_string, 'TK_STRING'];
   1.552 +                        }
   1.553 +                    }
   1.554 +                }
   1.555 +
   1.556 +
   1.557 +
   1.558 +            }
   1.559 +
   1.560 +            parser_pos += 1;
   1.561 +
   1.562 +            resulting_string += sep;
   1.563 +
   1.564 +            if (sep === '/') {
   1.565 +                // regexps may have modifiers /regexp/MOD , so fetch those, too
   1.566 +                while (parser_pos < input_length && in_array(input.charAt(parser_pos), wordchar)) {
   1.567 +                    resulting_string += input.charAt(parser_pos);
   1.568 +                    parser_pos += 1;
   1.569 +                }
   1.570 +            }
   1.571 +            return [resulting_string, 'TK_STRING'];
   1.572 +        }
   1.573 +
   1.574 +        if (c === '#') {
   1.575 +
   1.576 +
   1.577 +            if (output.length === 0 && input.charAt(parser_pos) === '!') {
   1.578 +                // shebang
   1.579 +                resulting_string = c;
   1.580 +                while (parser_pos < input_length && c !== '\n') {
   1.581 +                    c = input.charAt(parser_pos);
   1.582 +                    resulting_string += c;
   1.583 +                    parser_pos += 1;
   1.584 +                }
   1.585 +                output.push(trim(resulting_string) + '\n');
   1.586 +                print_newline();
   1.587 +                return get_next_token();
   1.588 +            }
   1.589 +
   1.590 +
   1.591 +
   1.592 +            // Spidermonkey-specific sharp variables for circular references
   1.593 +            // https://developer.mozilla.org/En/Sharp_variables_in_JavaScript
   1.594 +            // http://mxr.mozilla.org/mozilla-central/source/js/src/jsscan.cpp around line 1935
   1.595 +            var sharp = '#';
   1.596 +            if (parser_pos < input_length && in_array(input.charAt(parser_pos), digits)) {
   1.597 +                do {
   1.598 +                    c = input.charAt(parser_pos);
   1.599 +                    sharp += c;
   1.600 +                    parser_pos += 1;
   1.601 +                } while (parser_pos < input_length && c !== '#' && c !== '=');
   1.602 +                if (c === '#') {
   1.603 +                    //
   1.604 +                } else if (input.charAt(parser_pos) === '[' && input.charAt(parser_pos + 1) === ']') {
   1.605 +                    sharp += '[]';
   1.606 +                    parser_pos += 2;
   1.607 +                } else if (input.charAt(parser_pos) === '{' && input.charAt(parser_pos + 1) === '}') {
   1.608 +                    sharp += '{}';
   1.609 +                    parser_pos += 2;
   1.610 +                }
   1.611 +                return [sharp, 'TK_WORD'];
   1.612 +            }
   1.613 +        }
   1.614 +
   1.615 +        if (c === '<' && input.substring(parser_pos - 1, parser_pos + 3) === '<!--') {
   1.616 +            parser_pos += 3;
   1.617 +            c = '<!--';
   1.618 +            while (input.charAt(parser_pos) !== '\n' && parser_pos < input_length) {
   1.619 +                c += input.charAt(parser_pos);
   1.620 +                parser_pos++;
   1.621 +            }
   1.622 +            flags.in_html_comment = true;
   1.623 +            return [c, 'TK_COMMENT'];
   1.624 +        }
   1.625 +
   1.626 +        if (c === '-' && flags.in_html_comment && input.substring(parser_pos - 1, parser_pos + 2) === '-->') {
   1.627 +            flags.in_html_comment = false;
   1.628 +            parser_pos += 2;
   1.629 +            if (wanted_newline) {
   1.630 +                print_newline();
   1.631 +            }
   1.632 +            return ['-->', 'TK_COMMENT'];
   1.633 +        }
   1.634 +
   1.635 +        if (in_array(c, punct)) {
   1.636 +            while (parser_pos < input_length && in_array(c + input.charAt(parser_pos), punct)) {
   1.637 +                c += input.charAt(parser_pos);
   1.638 +                parser_pos += 1;
   1.639 +                if (parser_pos >= input_length) {
   1.640 +                    break;
   1.641 +                }
   1.642 +            }
   1.643 +
   1.644 +            if (c === ',') {
   1.645 +                return [c, 'TK_COMMA'];
   1.646 +            } else if (c === '=') {
   1.647 +                return [c, 'TK_EQUALS'];
   1.648 +            } else {
   1.649 +                return [c, 'TK_OPERATOR'];
   1.650 +            }
   1.651 +        }
   1.652 +
   1.653 +        return [c, 'TK_UNKNOWN'];
   1.654 +    }
   1.655 +
   1.656 +    //----------------------------------
   1.657 +    indent_string = '';
   1.658 +    while (opt_indent_size > 0) {
   1.659 +        indent_string += opt_indent_char;
   1.660 +        opt_indent_size -= 1;
   1.661 +    }
   1.662 +
   1.663 +    while (js_source_text && (js_source_text.charAt(0) === ' ' || js_source_text.charAt(0) === '\t')) {
   1.664 +        preindent_string += js_source_text.charAt(0);
   1.665 +        js_source_text = js_source_text.substring(1);
   1.666 +    }
   1.667 +    input = js_source_text;
   1.668 +
   1.669 +    last_word = ''; // last 'TK_WORD' passed
   1.670 +    last_type = 'TK_START_EXPR'; // last token type
   1.671 +    last_text = ''; // last token text
   1.672 +    last_last_text = ''; // pre-last token text
   1.673 +    output = [];
   1.674 +
   1.675 +    do_block_just_closed = false;
   1.676 +
   1.677 +    whitespace = "\n\r\t ".split('');
   1.678 +    wordchar = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$'.split('');
   1.679 +    digits = '0123456789'.split('');
   1.680 +
   1.681 +    punct = '+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |= ::';
   1.682 +    punct += ' <%= <% %> <?= <? ?>'; // try to be a good boy and try not to break the markup language identifiers
   1.683 +    punct = punct.split(' ');
   1.684 +
   1.685 +    // words which should always start on new line.
   1.686 +    line_starters = 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function'.split(',');
   1.687 +
   1.688 +    // states showing if we are currently in expression (i.e. "if" case) - 'EXPRESSION', or in usual block (like, procedure), 'BLOCK'.
   1.689 +    // some formatting depends on that.
   1.690 +    flag_store = [];
   1.691 +    set_mode('BLOCK');
   1.692 +
   1.693 +    parser_pos = 0;
   1.694 +    while (true) {
   1.695 +        var t = get_next_token();
   1.696 +        token_text = t[0];
   1.697 +        token_type = t[1];
   1.698 +        if (token_type === 'TK_EOF') {
   1.699 +            break;
   1.700 +        }
   1.701 +
   1.702 +        switch (token_type) {
   1.703 +
   1.704 +        case 'TK_START_EXPR':
   1.705 +
   1.706 +            if (token_text === '[') {
   1.707 +
   1.708 +                if (last_type === 'TK_WORD' || last_text === ')') {
   1.709 +                    // this is array index specifier, break immediately
   1.710 +                    // a[x], fn()[x]
   1.711 +                    if (in_array(last_text, line_starters)) {
   1.712 +                        print_single_space();
   1.713 +                    }
   1.714 +                    set_mode('(EXPRESSION)');
   1.715 +                    print_token();
   1.716 +                    break;
   1.717 +                }
   1.718 +
   1.719 +                if (flags.mode === '[EXPRESSION]' || flags.mode === '[INDENTED-EXPRESSION]') {
   1.720 +                    if (last_last_text === ']' && last_text === ',') {
   1.721 +                        // ], [ goes to new line
   1.722 +                        if (flags.mode === '[EXPRESSION]') {
   1.723 +                            flags.mode = '[INDENTED-EXPRESSION]';
   1.724 +                            if (!opt_keep_array_indentation) {
   1.725 +                                indent();
   1.726 +                            }
   1.727 +                        }
   1.728 +                        set_mode('[EXPRESSION]');
   1.729 +                        if (!opt_keep_array_indentation) {
   1.730 +                            print_newline();
   1.731 +                        }
   1.732 +                    } else if (last_text === '[') {
   1.733 +                        if (flags.mode === '[EXPRESSION]') {
   1.734 +                            flags.mode = '[INDENTED-EXPRESSION]';
   1.735 +                            if (!opt_keep_array_indentation) {
   1.736 +                                indent();
   1.737 +                            }
   1.738 +                        }
   1.739 +                        set_mode('[EXPRESSION]');
   1.740 +
   1.741 +                        if (!opt_keep_array_indentation) {
   1.742 +                            print_newline();
   1.743 +                        }
   1.744 +                    } else {
   1.745 +                        set_mode('[EXPRESSION]');
   1.746 +                    }
   1.747 +                } else {
   1.748 +                    set_mode('[EXPRESSION]');
   1.749 +                }
   1.750 +
   1.751 +
   1.752 +
   1.753 +            } else {
   1.754 +                if (last_word === 'for') {
   1.755 +                    set_mode('(FOR-EXPRESSION)');
   1.756 +                } else if (in_array(last_word, ['if', 'while'])) {
   1.757 +                    set_mode('(COND-EXPRESSION)');
   1.758 +                } else {
   1.759 +                    set_mode('(EXPRESSION)');
   1.760 +                }
   1.761 +            }
   1.762 +
   1.763 +            if (last_text === ';' || last_type === 'TK_START_BLOCK') {
   1.764 +                print_newline();
   1.765 +            } else if (last_type === 'TK_END_EXPR' || last_type === 'TK_START_EXPR' || last_type === 'TK_END_BLOCK' || last_text === '.') {
   1.766 +                if (wanted_newline) {
   1.767 +                    print_newline();
   1.768 +                }
   1.769 +                // do nothing on (( and )( and ][ and ]( and .(
   1.770 +            } else if (last_type !== 'TK_WORD' && last_type !== 'TK_OPERATOR') {
   1.771 +                print_single_space();
   1.772 +            } else if (last_word === 'function' || last_word === 'typeof') {
   1.773 +                // function() vs function ()
   1.774 +                if (opt_jslint_happy) {
   1.775 +                    print_single_space();
   1.776 +                }
   1.777 +            } else if (in_array(last_text, line_starters) || last_text === 'catch') {
   1.778 +                if (opt_space_before_conditional) {
   1.779 +                    print_single_space();
   1.780 +                }
   1.781 +            }
   1.782 +            print_token();
   1.783 +
   1.784 +            break;
   1.785 +
   1.786 +        case 'TK_END_EXPR':
   1.787 +            if (token_text === ']') {
   1.788 +                if (opt_keep_array_indentation) {
   1.789 +                    if (last_text === '}') {
   1.790 +                        // trim_output();
   1.791 +                        // print_newline(true);
   1.792 +                        remove_indent();
   1.793 +                        print_token();
   1.794 +                        restore_mode();
   1.795 +                        break;
   1.796 +                    }
   1.797 +                } else {
   1.798 +                    if (flags.mode === '[INDENTED-EXPRESSION]') {
   1.799 +                        if (last_text === ']') {
   1.800 +                            restore_mode();
   1.801 +                            print_newline();
   1.802 +                            print_token();
   1.803 +                            break;
   1.804 +                        }
   1.805 +                    }
   1.806 +                }
   1.807 +            }
   1.808 +            restore_mode();
   1.809 +            print_token();
   1.810 +            break;
   1.811 +
   1.812 +        case 'TK_START_BLOCK':
   1.813 +
   1.814 +            if (last_word === 'do') {
   1.815 +                set_mode('DO_BLOCK');
   1.816 +            } else {
   1.817 +                set_mode('BLOCK');
   1.818 +            }
   1.819 +            if (opt_brace_style === "expand" || opt_brace_style === "expand-strict") {
   1.820 +                var empty_braces = false;
   1.821 +                if (opt_brace_style === "expand-strict") {
   1.822 +                    empty_braces = (look_up() === '}');
   1.823 +                    if (!empty_braces) {
   1.824 +                        print_newline(true);
   1.825 +                    }
   1.826 +                } else {
   1.827 +                    if (last_type !== 'TK_OPERATOR') {
   1.828 +                        if (last_text === '=' || (is_special_word(last_text) && last_text !== 'else')) {
   1.829 +                            print_single_space();
   1.830 +                        } else {
   1.831 +                            print_newline(true);
   1.832 +                        }
   1.833 +                    }
   1.834 +                }
   1.835 +                print_token();
   1.836 +                if (!empty_braces) {
   1.837 +                    indent();
   1.838 +                }
   1.839 +            } else {
   1.840 +                if (last_type !== 'TK_OPERATOR' && last_type !== 'TK_START_EXPR') {
   1.841 +                    if (last_type === 'TK_START_BLOCK') {
   1.842 +                        print_newline();
   1.843 +                    } else {
   1.844 +                        print_single_space();
   1.845 +                    }
   1.846 +                } else {
   1.847 +                    // if TK_OPERATOR or TK_START_EXPR
   1.848 +                    if (is_array(flags.previous_mode) && last_text === ',') {
   1.849 +                        if (last_last_text === '}') {
   1.850 +                            // }, { in array context
   1.851 +                            print_single_space();
   1.852 +                        } else {
   1.853 +                            print_newline(); // [a, b, c, {
   1.854 +                        }
   1.855 +                    }
   1.856 +                }
   1.857 +                indent();
   1.858 +                print_token();
   1.859 +            }
   1.860 +
   1.861 +            break;
   1.862 +
   1.863 +        case 'TK_END_BLOCK':
   1.864 +            restore_mode();
   1.865 +            if (opt_brace_style === "expand" || opt_brace_style === "expand-strict") {
   1.866 +                if (last_text !== '{') {
   1.867 +                    print_newline();
   1.868 +                }
   1.869 +                print_token();
   1.870 +            } else {
   1.871 +                if (last_type === 'TK_START_BLOCK') {
   1.872 +                    // nothing
   1.873 +                    if (just_added_newline) {
   1.874 +                        remove_indent();
   1.875 +                    } else {
   1.876 +                        // {}
   1.877 +                        trim_output();
   1.878 +                    }
   1.879 +                } else {
   1.880 +                    if (is_array(flags.mode) && opt_keep_array_indentation) {
   1.881 +                        // we REALLY need a newline here, but newliner would skip that
   1.882 +                        opt_keep_array_indentation = false;
   1.883 +                        print_newline();
   1.884 +                        opt_keep_array_indentation = true;
   1.885 +
   1.886 +                    } else {
   1.887 +                        print_newline();
   1.888 +                    }
   1.889 +                }
   1.890 +                print_token();
   1.891 +            }
   1.892 +            break;
   1.893 +
   1.894 +        case 'TK_WORD':
   1.895 +
   1.896 +            // no, it's not you. even I have problems understanding how this works
   1.897 +            // and what does what.
   1.898 +            if (do_block_just_closed) {
   1.899 +                // do {} ## while ()
   1.900 +                print_single_space();
   1.901 +                print_token();
   1.902 +                print_single_space();
   1.903 +                do_block_just_closed = false;
   1.904 +                break;
   1.905 +            }
   1.906 +
   1.907 +            prefix = 'NONE';
   1.908 +
   1.909 +            if (token_text === 'function') {
   1.910 +                if (flags.var_line && last_type !== 'TK_EQUALS' ) {
   1.911 +                    flags.var_line_reindented = true;
   1.912 +                }
   1.913 +                if ((just_added_newline || last_text === ';') && last_text !== '{'
   1.914 +                && last_type !== 'TK_BLOCK_COMMENT' && last_type !== 'TK_COMMENT') {
   1.915 +                    // make sure there is a nice clean space of at least one blank line
   1.916 +                    // before a new function definition
   1.917 +                    n_newlines = just_added_newline ? n_newlines : 0;
   1.918 +                    if (!opt_preserve_newlines) {
   1.919 +                        n_newlines = 1;
   1.920 +                    }
   1.921 +
   1.922 +                    for (var i = 0; i < 2 - n_newlines; i++) {
   1.923 +                        print_newline(false);
   1.924 +                    }
   1.925 +                }
   1.926 +                if (last_type === 'TK_WORD') {
   1.927 +                    if (last_text === 'get' || last_text === 'set' || last_text === 'new' || last_text === 'return') {
   1.928 +                        print_single_space();
   1.929 +                    } else {
   1.930 +                        print_newline();
   1.931 +                    }
   1.932 +                } else if (last_type === 'TK_OPERATOR' || last_text === '=') {
   1.933 +                    // foo = function
   1.934 +                    print_single_space();
   1.935 +                } else if (is_expression(flags.mode)) {
   1.936 +                        //รครค print nothing
   1.937 +                } else {
   1.938 +                    print_newline();
   1.939 +                }
   1.940 +
   1.941 +                print_token();
   1.942 +                last_word = token_text;
   1.943 +                break;
   1.944 +            }
   1.945 +
   1.946 +            if (token_text === 'case' || (token_text === 'default' && flags.in_case_statement)) {
   1.947 +                if (last_text === ':' || flags.case_body) {
   1.948 +                    // switch cases following one another
   1.949 +                    remove_indent();
   1.950 +                } else {
   1.951 +                    // case statement starts in the same line where switch
   1.952 +                    if (!opt_indent_case) {
   1.953 +                        flags.indentation_level--;
   1.954 +                    }
   1.955 +                    print_newline();
   1.956 +                    if (!opt_indent_case) {
   1.957 +                        flags.indentation_level++;
   1.958 +                    }
   1.959 +                }
   1.960 +                print_token();
   1.961 +                flags.in_case = true;
   1.962 +                flags.in_case_statement = true;
   1.963 +                flags.case_body = false;
   1.964 +                break;
   1.965 +            }
   1.966 +
   1.967 +            if (last_type === 'TK_END_BLOCK') {
   1.968 +
   1.969 +                if (!in_array(token_text.toLowerCase(), ['else', 'catch', 'finally'])) {
   1.970 +                    prefix = 'NEWLINE';
   1.971 +                } else {
   1.972 +                    if (opt_brace_style === "expand" || opt_brace_style === "end-expand" || opt_brace_style === "expand-strict") {
   1.973 +                        prefix = 'NEWLINE';
   1.974 +                    } else {
   1.975 +                        prefix = 'SPACE';
   1.976 +                        print_single_space();
   1.977 +                    }
   1.978 +                }
   1.979 +            } else if (last_type === 'TK_SEMICOLON' && (flags.mode === 'BLOCK' || flags.mode === 'DO_BLOCK')) {
   1.980 +                prefix = 'NEWLINE';
   1.981 +            } else if (last_type === 'TK_SEMICOLON' && is_expression(flags.mode)) {
   1.982 +                prefix = 'SPACE';
   1.983 +            } else if (last_type === 'TK_STRING') {
   1.984 +                prefix = 'NEWLINE';
   1.985 +            } else if (last_type === 'TK_WORD') {
   1.986 +                if (last_text === 'else') {
   1.987 +                    // eat newlines between ...else *** some_op...
   1.988 +                    // won't preserve extra newlines in this place (if any), but don't care that much
   1.989 +                    trim_output(true);
   1.990 +                }
   1.991 +                prefix = 'SPACE';
   1.992 +            } else if (last_type === 'TK_START_BLOCK') {
   1.993 +                prefix = 'NEWLINE';
   1.994 +            } else if (last_type === 'TK_END_EXPR') {
   1.995 +                print_single_space();
   1.996 +                prefix = 'NEWLINE';
   1.997 +            }
   1.998 +
   1.999 +            if (in_array(token_text, line_starters) && last_text !== ')') {
  1.1000 +                if (last_text === 'else') {
  1.1001 +                    prefix = 'SPACE';
  1.1002 +                } else {
  1.1003 +                    prefix = 'NEWLINE';
  1.1004 +                }
  1.1005 +
  1.1006 +            }
  1.1007 +
  1.1008 +            if (flags.if_line && last_type === 'TK_END_EXPR') {
  1.1009 +                flags.if_line = false;
  1.1010 +            }
  1.1011 +            if (in_array(token_text.toLowerCase(), ['else', 'catch', 'finally'])) {
  1.1012 +                if (last_type !== 'TK_END_BLOCK' || opt_brace_style === "expand" || opt_brace_style === "end-expand" || opt_brace_style === "expand-strict") {
  1.1013 +                    print_newline();
  1.1014 +                } else {
  1.1015 +                    trim_output(true);
  1.1016 +                    print_single_space();
  1.1017 +                }
  1.1018 +            } else if (prefix === 'NEWLINE') {
  1.1019 +                if (is_special_word(last_text)) {
  1.1020 +                    // no newline between 'return nnn'
  1.1021 +                    print_single_space();
  1.1022 +                } else if (last_type !== 'TK_END_EXPR') {
  1.1023 +                    if ((last_type !== 'TK_START_EXPR' || token_text !== 'var') && last_text !== ':') {
  1.1024 +                        // no need to force newline on 'var': for (var x = 0...)
  1.1025 +                        if (token_text === 'if' && last_word === 'else' && last_text !== '{') {
  1.1026 +                            // no newline for } else if {
  1.1027 +                            print_single_space();
  1.1028 +                        } else {
  1.1029 +                            flags.var_line = false;
  1.1030 +                            flags.var_line_reindented = false;
  1.1031 +                            print_newline();
  1.1032 +                        }
  1.1033 +                    }
  1.1034 +                } else if (in_array(token_text, line_starters) && last_text !== ')') {
  1.1035 +                    flags.var_line = false;
  1.1036 +                    flags.var_line_reindented = false;
  1.1037 +                    print_newline();
  1.1038 +                }
  1.1039 +            } else if (is_array(flags.mode) && last_text === ',' && last_last_text === '}') {
  1.1040 +                print_newline(); // }, in lists get a newline treatment
  1.1041 +            } else if (prefix === 'SPACE') {
  1.1042 +                print_single_space();
  1.1043 +            }
  1.1044 +            print_token();
  1.1045 +            last_word = token_text;
  1.1046 +
  1.1047 +            if (token_text === 'var') {
  1.1048 +                flags.var_line = true;
  1.1049 +                flags.var_line_reindented = false;
  1.1050 +                flags.var_line_tainted = false;
  1.1051 +            }
  1.1052 +
  1.1053 +            if (token_text === 'if') {
  1.1054 +                flags.if_line = true;
  1.1055 +            }
  1.1056 +            if (token_text === 'else') {
  1.1057 +                flags.if_line = false;
  1.1058 +            }
  1.1059 +
  1.1060 +            break;
  1.1061 +
  1.1062 +        case 'TK_SEMICOLON':
  1.1063 +
  1.1064 +            print_token();
  1.1065 +            flags.var_line = false;
  1.1066 +            flags.var_line_reindented = false;
  1.1067 +            if (flags.mode === 'OBJECT') {
  1.1068 +                // OBJECT mode is weird and doesn't get reset too well.
  1.1069 +                flags.mode = 'BLOCK';
  1.1070 +            }
  1.1071 +            break;
  1.1072 +
  1.1073 +        case 'TK_STRING':
  1.1074 +
  1.1075 +            if (last_type === 'TK_END_EXPR' && in_array(flags.previous_mode, ['(COND-EXPRESSION)', '(FOR-EXPRESSION)'])) {
  1.1076 +                print_single_space();
  1.1077 +            } else if (last_type === 'TK_COMMENT' || last_type === 'TK_STRING' || last_type === 'TK_START_BLOCK' || last_type === 'TK_END_BLOCK' || last_type === 'TK_SEMICOLON') {
  1.1078 +                print_newline();
  1.1079 +            } else if (last_type === 'TK_WORD') {
  1.1080 +                print_single_space();
  1.1081 +            }
  1.1082 +            print_token();
  1.1083 +            break;
  1.1084 +
  1.1085 +        case 'TK_EQUALS':
  1.1086 +            if (flags.var_line) {
  1.1087 +                // just got an '=' in a var-line, different formatting/line-breaking, etc will now be done
  1.1088 +                flags.var_line_tainted = true;
  1.1089 +            }
  1.1090 +            print_single_space();
  1.1091 +            print_token();
  1.1092 +            print_single_space();
  1.1093 +            break;
  1.1094 +
  1.1095 +        case 'TK_COMMA':
  1.1096 +            if (flags.var_line) {
  1.1097 +                if (is_expression(flags.mode) || last_type === 'TK_END_BLOCK' ) {
  1.1098 +                    // do not break on comma, for(var a = 1, b = 2)
  1.1099 +                    flags.var_line_tainted = false;
  1.1100 +                }
  1.1101 +                if (flags.var_line_tainted) {
  1.1102 +                    print_token();
  1.1103 +                    flags.var_line_reindented = true;
  1.1104 +                    flags.var_line_tainted = false;
  1.1105 +                    print_newline();
  1.1106 +                    break;
  1.1107 +                } else {
  1.1108 +                    flags.var_line_tainted = false;
  1.1109 +                }
  1.1110 +
  1.1111 +                print_token();
  1.1112 +                print_single_space();
  1.1113 +                break;
  1.1114 +            }
  1.1115 +
  1.1116 +            if (last_type === 'TK_COMMENT') {
  1.1117 +                print_newline();
  1.1118 +            }
  1.1119 +
  1.1120 +            if (last_type === 'TK_END_BLOCK' && flags.mode !== "(EXPRESSION)") {
  1.1121 +                print_token();
  1.1122 +                if (flags.mode === 'OBJECT' && last_text === '}') {
  1.1123 +                    print_newline();
  1.1124 +                } else {
  1.1125 +                    print_single_space();
  1.1126 +                }
  1.1127 +            } else {
  1.1128 +                if (flags.mode === 'OBJECT') {
  1.1129 +                    print_token();
  1.1130 +                    print_newline();
  1.1131 +                } else {
  1.1132 +                    // EXPR or DO_BLOCK
  1.1133 +                    print_token();
  1.1134 +                    print_single_space();
  1.1135 +                }
  1.1136 +            }
  1.1137 +            break;
  1.1138 +
  1.1139 +
  1.1140 +        case 'TK_OPERATOR':
  1.1141 +
  1.1142 +            var space_before = true;
  1.1143 +            var space_after = true;
  1.1144 +
  1.1145 +            if (is_special_word(last_text)) {
  1.1146 +                // "return" had a special handling in TK_WORD. Now we need to return the favor
  1.1147 +                print_single_space();
  1.1148 +                print_token();
  1.1149 +                break;
  1.1150 +            }
  1.1151 +
  1.1152 +            // hack for actionscript's import .*;
  1.1153 +            if (token_text === '*' && last_type === 'TK_UNKNOWN' && !last_last_text.match(/^\d+$/)) {
  1.1154 +                print_token();
  1.1155 +                break;
  1.1156 +            }
  1.1157 +
  1.1158 +            if (token_text === ':' && flags.in_case) {
  1.1159 +                if (opt_indent_case) {
  1.1160 +                    flags.case_body = true;
  1.1161 +                }
  1.1162 +                print_token(); // colon really asks for separate treatment
  1.1163 +                print_newline();
  1.1164 +                flags.in_case = false;
  1.1165 +                break;
  1.1166 +            }
  1.1167 +
  1.1168 +            if (token_text === '::') {
  1.1169 +                // no spaces around exotic namespacing syntax operator
  1.1170 +                print_token();
  1.1171 +                break;
  1.1172 +            }
  1.1173 +
  1.1174 +            if (in_array(token_text, ['--', '++', '!']) || (in_array(token_text, ['-', '+']) && (in_array(last_type, ['TK_START_BLOCK', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR']) || in_array(last_text, line_starters)))) {
  1.1175 +                // unary operators (and binary +/- pretending to be unary) special cases
  1.1176 +
  1.1177 +                space_before = false;
  1.1178 +                space_after = false;
  1.1179 +
  1.1180 +                if (last_text === ';' && is_expression(flags.mode)) {
  1.1181 +                    // for (;; ++i)
  1.1182 +                    //        ^^^
  1.1183 +                    space_before = true;
  1.1184 +                }
  1.1185 +                if (last_type === 'TK_WORD' && in_array(last_text, line_starters)) {
  1.1186 +                    space_before = true;
  1.1187 +                }
  1.1188 +
  1.1189 +                if (flags.mode === 'BLOCK' && (last_text === '{' || last_text === ';')) {
  1.1190 +                    // { foo; --i }
  1.1191 +                    // foo(); --bar;
  1.1192 +                    print_newline();
  1.1193 +                }
  1.1194 +            } else if (token_text === '.') {
  1.1195 +                // decimal digits or object.property
  1.1196 +                space_before = false;
  1.1197 +
  1.1198 +            } else if (token_text === ':') {
  1.1199 +                if (flags.ternary_depth === 0) {
  1.1200 +                    if (flags.mode === 'BLOCK') {
  1.1201 +                        flags.mode = 'OBJECT';
  1.1202 +                    }
  1.1203 +                    space_before = false;
  1.1204 +                } else {
  1.1205 +                    flags.ternary_depth -= 1;
  1.1206 +                }
  1.1207 +            } else if (token_text === '?') {
  1.1208 +                flags.ternary_depth += 1;
  1.1209 +            }
  1.1210 +            if (space_before) {
  1.1211 +                print_single_space();
  1.1212 +            }
  1.1213 +
  1.1214 +            print_token();
  1.1215 +
  1.1216 +            if (space_after) {
  1.1217 +                print_single_space();
  1.1218 +            }
  1.1219 +
  1.1220 +            break;
  1.1221 +
  1.1222 +        case 'TK_BLOCK_COMMENT':
  1.1223 +
  1.1224 +            var lines = split_newlines(token_text);
  1.1225 +            var j; // iterator for this case
  1.1226 +
  1.1227 +            if (all_lines_start_with(lines.slice(1), '*')) {
  1.1228 +                // javadoc: reformat and reindent
  1.1229 +                print_newline();
  1.1230 +                output.push(lines[0]);
  1.1231 +                for (j = 1; j < lines.length; j++) {
  1.1232 +                    print_newline();
  1.1233 +                    output.push(' ');
  1.1234 +                    output.push(trim(lines[j]));
  1.1235 +                }
  1.1236 +
  1.1237 +            } else {
  1.1238 +
  1.1239 +                // simple block comment: leave intact
  1.1240 +                if (lines.length > 1) {
  1.1241 +                    // multiline comment block starts with a new line
  1.1242 +                    print_newline();
  1.1243 +                } else {
  1.1244 +                    // single-line /* comment */ stays where it is
  1.1245 +                    if (last_type === 'TK_END_BLOCK') {
  1.1246 +                        print_newline();
  1.1247 +                    } else {
  1.1248 +                        print_single_space();
  1.1249 +                    }
  1.1250 +
  1.1251 +                }
  1.1252 +
  1.1253 +                for (j = 0; j < lines.length; j++) {
  1.1254 +                    output.push(lines[j]);
  1.1255 +                    output.push("\n");
  1.1256 +                }
  1.1257 +
  1.1258 +            }
  1.1259 +            if (look_up('\n') !== '\n') {
  1.1260 +                print_newline();
  1.1261 +            }
  1.1262 +            break;
  1.1263 +
  1.1264 +        case 'TK_INLINE_COMMENT':
  1.1265 +            print_single_space();
  1.1266 +            print_token();
  1.1267 +            if (is_expression(flags.mode)) {
  1.1268 +                print_single_space();
  1.1269 +            } else {
  1.1270 +                force_newline();
  1.1271 +            }
  1.1272 +            break;
  1.1273 +
  1.1274 +        case 'TK_COMMENT':
  1.1275 +
  1.1276 +            if (last_text === ',' && !wanted_newline) {
  1.1277 +                trim_output(true);
  1.1278 +            }
  1.1279 +            if (last_type !== 'TK_COMMENT') {
  1.1280 +                if (wanted_newline) {
  1.1281 +                    print_newline();
  1.1282 +                } else {
  1.1283 +                    print_single_space();
  1.1284 +                }
  1.1285 +            }
  1.1286 +            print_token();
  1.1287 +            print_newline();
  1.1288 +            break;
  1.1289 +
  1.1290 +        case 'TK_UNKNOWN':
  1.1291 +            if (is_special_word(last_text)) {
  1.1292 +                print_single_space();
  1.1293 +            }
  1.1294 +            print_token();
  1.1295 +            break;
  1.1296 +        }
  1.1297 +
  1.1298 +        last_last_text = last_text;
  1.1299 +        last_type = token_type;
  1.1300 +        last_text = token_text;
  1.1301 +    }
  1.1302 +
  1.1303 +    var sweet_code = preindent_string + output.join('').replace(/[\r\n ]+$/, '');
  1.1304 +    return sweet_code;
  1.1305 +
  1.1306 +}

mercurial